TMB/0000755000176200001440000000000014536106351010700 5ustar liggesusersTMB/NAMESPACE0000644000176200001440000000375114417511650012125 0ustar liggesusers ###____________________ IMPORTS ___________________________________ ## Base R - packages ---------------------- importFrom("graphics", abline, legend, matplot, plot) importFrom("methods", as, is, new, cbind2, rbind2) importFrom("stats", approx, confint, integrate, median, nlminb, optim, optimHess, pchisq, qchisq, qnorm, rnorm, runif, sd, splinefun, uniroot, var, ks.test) importFrom("utils", as.relistable, relist, head, tail) ## Windows specific imports if(.Platform$OS.type == "windows"){ importFrom("utils", shortPathName) } ## TMB:::install.contrib importFrom("utils", download.file, file_test, unzip) ## TMB:::.onLoad importFrom("utils", packageVersion) ## Recommended R - packages ---------------------- importClassesFrom("Matrix")# all currently (FIXME) , corMatrix, dgCMatrix, dgTMatrix, dpoMatrix) importMethodsFrom("Matrix", coerce, cov2cor, determinant, drop, "%*%", crossprod,tcrossprod, t, diag, chol2inv, solve, colSums,rowSums) importFrom("Matrix", Cholesky, forceSymmetric, invPerm, tril, triu, Diagonal) ###____________________ EXPORTS ___________________________________ export(benchmark, checkConsistency, compile, config, dynlib, FreeADFun, gdbsource, MakeADFun, newton, newtonOption, normalize, oneStepPredict, openmp, plot.parallelBenchmark, plot.tmbprofile, precompile, print.backtrace, print.checkConsistency, print.sdreport, Rinterface, runExample, runSymbolicAnalysis, sdreport, SR, summary.checkConsistency, summary.sdreport, template, tmbprofile, tmbroot) ## Methods : S3method(confint, tmbprofile) S3method(plot, tmbprofile) S3method(print, sdreport) S3method(summary, sdreport) S3method(as.list, sdreport) S3method(plot, parallelBenchmark) S3method(print, backtrace) S3method(print, checkConsistency) S3method(summary, checkConsistency) TMB/man/0000755000176200001440000000000014527235235011457 5ustar liggesusersTMB/man/benchmark.Rd0000644000176200001440000000300014417511650013665 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/benchmark.R \name{benchmark} \alias{benchmark} \alias{plot.parallelBenchmark} \title{Benchmark parallel templates} \usage{ benchmark(obj, n = 10, expr = NULL, cores = NULL) \method{plot}{parallelBenchmark}(x, type = "b", ..., show = c("speedup", "time"), legendpos = "topleft") } \arguments{ \item{obj}{Object from \code{MakeADFun}} \item{n}{Number of replicates to obtain reliable results.} \item{expr}{Optional expression to benchmark instead of default.} \item{cores}{Optional vector of cores.} \item{x}{Object to plot} \item{type}{Plot type} \item{...}{Further plot arguments} \item{show}{Plot relative speedup or relative time?} \item{legendpos}{Position of legend} } \description{ Benchmark parallel templates Plot result of parallel benchmark } \details{ By default this function will perform timings of the most critical parts of an AD model, specifically \enumerate{ \item Objective function of evaluated template. \item Gradient of evaluated template. \item Sparse hessian of evaluated template. \item Cholesky factorization of sparse hessian. } (for pure fixed effect models only the first two). Expressions to time can be overwritten by the user (\code{expr}). A \code{plot} method is available for Parallel benchmarks. } \examples{ \dontrun{ runExample("linreg_parallel",thisR=TRUE) ## Create obj ben <- benchmark(obj,n=100,cores=1:4) plot(ben) ben <- benchmark(obj,n=10,cores=1:4,expr=expression(do.call("optim",obj))) plot(ben) } } TMB/man/Rinterface.Rd0000644000176200001440000000066014113627761014032 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{Rinterface} \alias{Rinterface} \title{Create minimal R-code corresponding to a cpp template.} \usage{ Rinterface(file) } \arguments{ \item{file}{cpp template file.} } \description{ Create a skeleton of required R-code once the cpp template is ready. } \examples{ file <- system.file("examples/simple.cpp", package = "TMB") Rinterface(file) } TMB/man/config.Rd0000644000176200001440000000165414113627761013221 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/config.R \name{config} \alias{config} \title{Get or set internal configuration variables} \usage{ config(..., DLL = getUserDLL()) } \arguments{ \item{...}{Variables to set} \item{DLL}{Name of user's DLL. Auto-detected if missing.} } \value{ List with current configuration } \description{ Get or set internal configuration variables of user's DLL. } \details{ A model compiled with the \code{TMB} C++ library has several configuration variables set by default. The variables can be read and modified using this function. The meaning of the variables can be found in the Doxygen documentation. } \examples{ \dontrun{ ## Load library dyn.load(dynlib("mymodel")) ## Read the current settings config(DLL="mymodel") ## Reduce memory peak of a parallel model by creating tapes in serial config(tape.parallel=0, DLL="mymodel") obj <- MakeADFun(..., DLL="mymodel") } } TMB/man/runExample.Rd0000644000176200001440000000145614417511650014070 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/examples.R \name{runExample} \alias{runExample} \title{Run one of the test examples.} \usage{ runExample( name = NULL, all = FALSE, thisR = TRUE, clean = FALSE, exfolder = NULL, dontrun = FALSE, subarch = TRUE, ... ) } \arguments{ \item{name}{Character name of example.} \item{all}{Run all the test examples?} \item{thisR}{Run inside this R?} \item{clean}{Cleanup before compile?} \item{exfolder}{Alternative folder with examples.} \item{dontrun}{Build only (don't run) and remove temporary object files ?} \item{subarch}{Build in sub-architecture specific folder ?} \item{...}{Passed to \code{\link{compile}}.} } \description{ Compile and run a test example (\code{runExample()} shows all available examples). } TMB/man/GK.Rd0000644000176200001440000000055214243720032012236 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{GK} \alias{GK} \title{Gauss Kronrod configuration} \usage{ GK(...) } \arguments{ \item{...}{See source code} } \description{ Helper function to specify parameters used by the Gauss Kronrod integration available through the argument \code{integrate} to \code{MakeADFun}. } TMB/man/SR.Rd0000644000176200001440000000105514243720032012260 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{SR} \alias{SR} \title{Sequential reduction configuration} \usage{ SR(x, discrete = FALSE) } \arguments{ \item{x}{Breaks defining the domain of integration} \item{discrete}{Boolean defining integration wrt Lebesgue measure (\code{discrete=FALSE}) or counting measure \code{discrete=TRUE}.} } \description{ Helper function to specify an integration grid used by the sequential reduction algorithm available through the argument \code{integrate} to \code{MakeADFun}. } TMB/man/gdbsource.Rd0000644000176200001440000000255614113627761013733 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/gdbsource.R \name{gdbsource} \alias{gdbsource} \alias{print.backtrace} \title{Source R-script through gdb to get backtrace.} \usage{ gdbsource(file, interactive = FALSE) \method{print}{backtrace}(x, ...) } \arguments{ \item{file}{Your R script} \item{interactive}{Run interactive gdb session?} \item{x}{Backtrace from \code{gdbsource}} \item{...}{Not used} } \value{ Object of class \code{backtrace} } \description{ Source R-script through gdb to get backtrace. If \code{gdbsource} is run non-interactively (the default) only the relevant information will be printed. } \details{ This function is useful for debugging templates. If a script aborts e.g. due to an out-of-bound index operation it should be fast to locate the line that caused the problem by running \code{gdbsource(file)}. Alternatively, If more detailed debugging is required, then \code{gdbsource(file,TRUE)} will provide the full backtrace followed by an interactive gdb session where the individual frames can be inspected. Note that templates should be compiled without optimization and with debug information in order to provide correct line numbers: \itemize{ \item On Linux/OS X use \code{compile(cppfile,"-O0 -g")}. \item On Windows use \code{compile(cppfile,"-O1 -g",DLLFLAGS="")} (lower optimization level will cause errors). } } TMB/man/MakeADFun.Rd0000644000176200001440000002256514417511650013507 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{MakeADFun} \alias{MakeADFun} \title{Construct objective functions with derivatives based on a compiled C++ template.} \usage{ MakeADFun( data, parameters, map = list(), type = c("ADFun", "Fun", "ADGrad"[!intern && (!is.null(random) || !is.null(profile))]), random = NULL, profile = NULL, random.start = expression(last.par.best[random]), hessian = FALSE, method = "BFGS", inner.method = "newton", inner.control = list(maxit = 1000), MCcontrol = list(doMC = FALSE, seed = 123, n = 100), ADreport = FALSE, atomic = TRUE, LaplaceNonZeroGradient = FALSE, DLL = getUserDLL(), checkParameterOrder = TRUE, regexp = FALSE, silent = FALSE, intern = FALSE, integrate = NULL, ... ) } \arguments{ \item{data}{List of data objects (vectors, matrices, arrays, factors, sparse matrices) required by the user template (order does not matter and un-used components are allowed).} \item{parameters}{List of all parameter objects required by the user template (both random and fixed effects).} \item{map}{List defining how to optionally collect and fix parameters - see details.} \item{type}{Character vector defining which operation stacks are generated from the users template - see details.} \item{random}{Character vector defining the random effect parameters. See also \code{regexp}.} \item{profile}{Parameters to profile out of the likelihood (this subset will be appended to \code{random} with Laplace approximation disabled).} \item{random.start}{Expression defining the strategy for choosing random effect initial values as function of previous function evaluations - see details.} \item{hessian}{Calculate Hessian at optimum?} \item{method}{Outer optimization method.} \item{inner.method}{Inner optimization method (see function "newton").} \item{inner.control}{List controlling inner optimization.} \item{MCcontrol}{List controlling importance sampler (turned off by default).} \item{ADreport}{Calculate derivatives of macro ADREPORT(vector) instead of objective_function return value?} \item{atomic}{Allow tape to contain atomic functions?} \item{LaplaceNonZeroGradient}{Allow Taylor expansion around non-stationary point?} \item{DLL}{Name of shared object file compiled by user (without the conventional extension, \file{.so}, \file{.dll}, \dots).} \item{checkParameterOrder}{Optional check for correct parameter order.} \item{regexp}{Match random effects by regular expressions?} \item{silent}{Disable all tracing information?} \item{intern}{Do Laplace approximation on C++ side ? See details (Experimental - may change without notice)} \item{integrate}{Specify alternative integration method(s) for random effects (see details)} \item{...}{Currently unused.} } \value{ List with components (fn, gr, etc) suitable for calling an R optimizer, such as \code{nlminb} or \code{optim}. } \description{ Construct objective functions with derivatives based on the users C++ template. } \details{ A call to \code{MakeADFun} will return an object that, based on the users DLL code (specified through \code{DLL}), contains functions to calculate the objective function and its gradient. The object contains the following components: \itemize{ \item \code{par} A default parameter. \item \code{fn} The likelihood function. \item \code{gr} The gradient function. \item \code{report} A function to report all variables reported with the REPORT() macro in the user template. \item \code{env} Environment with access to all parts of the structure. } and is thus ready for a call to an R optimizer, such as \code{nlminb} or \code{optim}. Data (\code{data}) and parameters (\code{parameters}) are directly read by the user template via the macros beginning with DATA_ and PARAMETER_. The order of the PARAMETER_ macros defines the order of parameters in the final objective function. There are no restrictions on the order of random parameters, fixed parameters or data in the template. } \note{ Do not rely upon the default arguments of any of the functions in the model object \code{obj$fn}, \code{obj$gr}, \code{obj$he}, \code{obj$report}. I.e. always use the explicit form \code{obj$fn(obj$par)} rather than \code{obj$fn()}. } \section{Parameter mapping}{ Optionally, a simple mechanism for collecting and fixing parameters from R is available through the \code{map} argument. A map is a named list of factors with the following properties: \itemize{ \item names(map) is a subset of names(parameters). \item For a parameter "p" length(map$p) equals length(parameters$p). \item Parameter entries with NAs in the factor are fixed. \item Parameter entries with equal factor level are collected to a common value. } More advanced parameter mapping, such as collecting parameters between different vectors etc., must be implemented from the template. } \section{Specifying random effects}{ Random effects are specified via the argument \code{random}: A component of the parameter list is marked as random if its name is matched by any of the characters of the vector \code{random} (Regular expression match is performed if \code{regexp=TRUE}). If some parameters are specified as random effects, these will be integrated out of the objective function via the Laplace approximation. In this situation the functions \code{fn} and \code{gr} automatically perform an optimization of random effects for each function evaluation. This is referred to as the 'inner optimization'. Strategies for choosing initial values of the inner optimization can be controlled via the argument \code{random.start}. The default is \code{expression(last.par.best[random])} where \code{last.par.best} is an internal full parameter vector corresponding to the currently best likelihood. An alternative choice could be \code{expression(last.par[random])} i.e. the random effect optimum of the most recent - not necessarily best - likelihood evaluation. Further control of the inner optimization can be obtained by the argument \code{inner.control} which is a list of control parameters for the inner optimizer \code{newton}. Depending of the inner optimization problem type the following settings are recommended: \enumerate{ \item Quasi-convex: \code{smartsearch=TRUE} (the default). \item Strictly-convex: \code{smartsearch=FALSE} and \code{maxit=20}. \item Quadratic: \code{smartsearch=FALSE} and \code{maxit=1}. } } \section{The model environment \code{env}}{ Technically, the user template is processed several times by inserting different types as template parameter, selected by argument \code{type}: \itemize{ \item \code{"ADFun"} Run through the template with AD-types and produce a stack of operations representing the objective function. \item \code{"Fun"} Run through the template with ordinary double-types. \item \code{"ADGrad"} Run through the template with nested AD-types and produce a stack of operations representing the objective function gradient. } Each of these are represented by external pointers to C++ structures available in the environment \code{env}. Further objects in the environment \code{env}: \itemize{ \item \code{validpar} Function defining the valid parameter region (by default no restrictions). If an invalid parameter is inserted \code{fn} immediately return NaN. \item \code{parList} Function to get the full parameter vector of random and fixed effects in a convenient list format. \item \code{random} An index vector of random effect positions in the full parameter vector. \item \code{last.par} Full parameter of the latest likelihood evaluation. \item \code{last.par.best} Full parameter of the best likelihood evaluation. \item \code{tracepar} Trace every likelihood evaluation ? \item \code{tracemgc} Trace maximum gradient component of every gradient evaluation ? \item \code{silent} Pass 'silent=TRUE' to all try-calls ? } } \section{The argument \code{intern}}{ By passing \code{intern=TRUE} the entire Laplace approximation (including sparse matrix calculations) is done within the AD machinery on the C++ side. This requires the model to be compiled using the 'TMBad framework' - see \code{\link{compile}}. For any serious use of this option one should consider compiling with \code{supernodal=TRUE} - again see \code{\link{compile}} - in order to get performance comparable to R's matrix calculations. The benefit of the 'intern' LA is that it may be faster in some cases and that it provides an autodiff hessian (\code{obj$he}) wrt. the fixed effects which would otherwise not work for random effect models. Another benefit is that it gives access to fast computations with certain hessian structures that do not meet the usual sparsity requirement. A detailed list of options are found in the online doxygen documentation in the 'newton' namespace under the 'newton_config' struct. All these options can be passed from R via the `inner.control` argument. However, there are some drawbacks of running the LA on the C++ side. Notably, random effects are no longer visible in the model environment which may break assumptions on the layout of internal vectors (`par`, `last.par`, etc). In addition, model debugging becomes harder when calculations are moved to C++. } \section{Controlling tracing}{ A high level of tracing information will be output by default when evaluating the objective function and gradient. This is useful while developing a model, but may eventually become annoying. Disable all tracing by passing \code{silent=TRUE} to the \code{MakeADFun} call. } TMB/man/oneStepPredict.Rd0000644000176200001440000002122614455504313014675 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/validation.R \name{oneStepPredict} \alias{oneStepPredict} \title{Calculate one-step-ahead (OSA) residuals for a latent variable model.} \usage{ oneStepPredict( obj, observation.name = NULL, data.term.indicator = NULL, method = c("oneStepGaussianOffMode", "fullGaussian", "oneStepGeneric", "oneStepGaussian", "cdf"), subset = NULL, conditional = NULL, discrete = NULL, discreteSupport = NULL, range = c(-Inf, Inf), seed = 123, parallel = FALSE, trace = TRUE, reverse = (method == "oneStepGaussianOffMode"), splineApprox = TRUE, ... ) } \arguments{ \item{obj}{Output from \code{MakeADFun}.} \item{observation.name}{Character naming the observation in the template.} \item{data.term.indicator}{Character naming an indicator data variable in the template (not required by all methods - see details).} \item{method}{Method to calculate OSA (see details).} \item{subset}{Index vector of observations that will be added one by one during OSA. By default \code{1:length(observations)} (with \code{conditional} subtracted).} \item{conditional}{Index vector of observations that are fixed during OSA. By default the empty set.} \item{discrete}{Logical; Are observations discrete? (assumed FALSE by default).} \item{discreteSupport}{Possible outcomes of discrete part of the distribution (\code{method="oneStepGeneric"} and \code{method="cdf"} only).} \item{range}{Possible range of continuous part of the distribution (\code{method="oneStepGeneric"} only).} \item{seed}{Randomization seed (discrete case only). If \code{NULL} the RNG seed is untouched by this routine (recommended for simulation studies).} \item{parallel}{Run in parallel using the \code{parallel} package?} \item{trace}{Logical; Trace progress? More options available for \code{method="oneStepGeneric"} - see details.} \item{reverse}{Do calculations in opposite order to improve stability? (currently enabled by default for \code{oneStepGaussianOffMode} method only)} \item{splineApprox}{Represent one-step conditional distribution by a spline to reduce number of density evaluations? (\code{method="oneStepGeneric"} only).} \item{...}{Control parameters for OSA method} } \value{ \code{data.frame} with OSA \emph{standardized} residuals in column \code{residual}. In addition, depending on the method, the output includes selected characteristics of the predictive distribution (current row) given past observations (past rows), notably the \emph{conditional} \describe{ \item{mean}{Expectation of the current observation} \item{sd}{Standard deviation of the current observation} \item{Fx}{CDF at current observation} \item{px}{Density at current observation} \item{nll}{Negative log density at current observation} \item{nlcdf.lower}{Negative log of the lower CDF at current observation} \item{nlcdf.upper}{Negative log of the upper CDF at current observation} } \emph{given past observations}. If column \code{randomize} is present, it indicates that randomization has been applied for the row. } \description{ Calculate one-step-ahead (OSA) residuals for a latent variable model. (\emph{Beta version; may change without notice}) } \details{ Given a TMB latent variable model this function calculates OSA standardized residuals that can be used for goodness-of-fit assessment. The approach is based on a factorization of the joint distribution of the \emph{observations} \eqn{X_1,...,X_n} into successive conditional distributions. Denote by \deqn{F_n(x_n) = P(X_n \leq x_n | X_1 = x_1,...,X_{n-1}=x_{n-1} )} the one-step-ahead CDF, and by \deqn{p_n(x_n) = P(X_n = x_n | X_1 = x_1,...,X_{n-1}=x_{n-1} )} the corresponding point probabilities (zero for continuous distributions). In case of continuous observations the sequence \deqn{\Phi^{-1}(F_1(X_1))\:,...,\:\Phi^{-1}(F_n(X_n))} will be iid standard normal. These are referred to as the OSA residuals. In case of discrete observations draw (unit) uniform variables \eqn{U_1,...,U_n} and construct the randomized OSA residuals \deqn{\Phi^{-1}(F_1(X_1)-U_1 p_1(X_1))\:,...,\:\Phi^{-1}(F_n(X_n)-U_n p_n(X_n))} These are also iid standard normal. } \section{Choosing the method}{ The user must specify the method used to calculate the residuals - see detailed list of method descriptions below. We note that all the methods are based on approximations. While the default 'oneStepGaussianoffMode' often represents a good compromise between accuracy and speed, it cannot be assumed to work well for all model classes. As a rule of thumb, if in doubt whether a method is accurate enough, you should always compare with the 'oneStepGeneric' which is considered the most accurate of the available methods. \describe{ \item{method="fullGaussian"}{ This method assumes that the joint distribution of data \emph{and} random effects is Gaussian (or well approximated by a Gaussian). It does not require any changes to the user template. However, if used in conjunction with \code{subset} and/or \code{conditional} a \code{data.term.indicator} is required - see the next method. } \item{method="oneStepGeneric"}{ This method calculates the one-step conditional probability density as a ratio of Laplace approximations. The approximation is integrated (and re-normalized for improved accuracy) using 1D numerical quadrature to obtain the one-step CDF evaluated at each data point. The method works in the continuous case as well as the discrete case (\code{discrete=TRUE}). It requires a specification of a \code{data.term.indicator} explained in the following. Suppose the template for the observations given the random effects (\eqn{u}) looks like \preformatted{ DATA_VECTOR(x); ... nll -= dnorm(x(i), u(i), sd(i), true); ... } Then this template can be augmented with a \code{data.term.indicator = "keep"} by changing the template to \preformatted{ DATA_VECTOR(x); DATA_VECTOR_INDICATOR(keep, x); ... nll -= keep(i) * dnorm(x(i), u(i), sd(i), true); ... } The new data vector (\code{keep}) need not be passed from \R. It automatically becomes a copy of \code{x} filled with ones. Some extra parameters are essential for the method. Pay special attention to the integration domain which must be set either via \code{range} (continuous case) or \code{discreteSupport} (discrete case). Both of these can be set simultanously to specify a mixed continuous/discrete distribution. For example, a non-negative distribution with a point mass at zero (e.g. the Tweedie distribution) should have \code{range=c(0,Inf)} and \code{discreteSupport=0}. Several parameters control accuracy and appropriate settings are case specific. By default, a spline is fitted to the one-step density before integration (\code{splineApprox=TRUE}) to reduce the number of density evaluations. However, this setting may have negative impact on accuracy. The spline approximation can then either be disabled or improved by noting that \code{...} arguments are passed to \link{tmbprofile}: Pass e.g. \code{ystep=20, ytol=0.1}. Finally, it may be useful to look at the one step predictive distributions on either log scale (\code{trace=2}) or natural scale (\code{trace=3}) to determine which alternative methods might be appropriate. } \item{method="oneStepGaussian"}{ This is a special case of the generic method where the one step conditional distribution is approximated by a Gaussian (and can therefore be handled more efficiently). } \item{method="oneStepGaussianOffMode"}{ This is an approximation of the "oneStepGaussian" method that avoids locating the mode of the one-step conditional density. } \item{method="cdf"}{ The generic method can be slow due to the many function evaluations used during the 1D integration (or summation in the discrete case). The present method can speed up this process but requires more changes to the user template. The above template must be expanded with information about how to calculate the negative log of the lower and upper CDF: \preformatted{ DATA_VECTOR(x); DATA_VECTOR_INDICATOR(keep, x); ... nll -= keep(i) * dnorm(x(i), u(i), sd(i), true); nll -= keep.cdf_lower(i) * log( pnorm(x(i), u(i), sd(i)) ); nll -= keep.cdf_upper(i) * log( 1.0 - pnorm(x(i), u(i), sd(i)) ); ... } The specialized members \code{keep.cdf_lower} and \code{keep.cdf_upper} automatically become copies of \code{x} filled with zeros. } } } \examples{ ######################## Gaussian case runExample("simple") osa.simple <- oneStepPredict(obj, observation.name = "x", method="fullGaussian") qqnorm(osa.simple$residual); abline(0,1) \dontrun{ ######################## Poisson case (First 100 observations) runExample("ar1xar1") osa.ar1xar1 <- oneStepPredict(obj, "N", "keep", method="cdf", discrete=TRUE, subset=1:100) qqnorm(osa.ar1xar1$residual); abline(0,1) } } TMB/man/newton.Rd0000644000176200001440000000510414417511650013254 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{newton} \alias{newton} \title{Generalized newton optimizer.} \usage{ newton( par, fn, gr, he, trace = 1, maxit = 100, tol = 1e-08, alpha = 1, smartsearch = TRUE, mgcmax = 1e+60, super = TRUE, silent = TRUE, ustep = 1, power = 0.5, u0 = 1e-04, grad.tol = tol, step.tol = tol, tol10 = 0.001, env = environment(), ... ) } \arguments{ \item{par}{Initial parameter.} \item{fn}{Objective function.} \item{gr}{Gradient function.} \item{he}{Sparse hessian function.} \item{trace}{Print tracing information?} \item{maxit}{Maximum number of iterations.} \item{tol}{Convergence tolerance.} \item{alpha}{Newton stepsize in the fixed stepsize case.} \item{smartsearch}{Turn on adaptive stepsize algorithm for non-convex problems?} \item{mgcmax}{Refuse to optimize if the maximum gradient component is too steep.} \item{super}{Supernodal Cholesky?} \item{silent}{Be silent?} \item{ustep}{Adaptive stepsize initial guess between 0 and 1.} \item{power}{Parameter controlling adaptive stepsize.} \item{u0}{Parameter controlling adaptive stepsize.} \item{grad.tol}{Gradient convergence tolerance.} \item{step.tol}{Stepsize convergence tolerance.} \item{tol10}{Try to exit if last 10 iterations not improved more than this.} \item{env}{Environment for cached Cholesky factor.} \item{...}{Currently unused.} } \value{ List with solution similar to \code{optim} output. } \description{ Generalized newton optimizer used for the inner optimization problem. } \details{ If \code{smartsearch=FALSE} this function performs an ordinary newton optimization on the function \code{fn} using an exact sparse hessian function. A fixed stepsize may be controlled by \code{alpha} so that the iterations are given by: \deqn{u_{n+1} = u_n - \alpha f''(u_n)^{-1}f'(u_n)} If \code{smartsearch=TRUE} the hessian is allowed to become negative definite preventing ordinary newton iterations. In this situation the newton iterations are performed on a modified objective function defined by adding a quadratic penalty around the expansion point \eqn{u_0}: \deqn{f_{t}(u) = f(u) + \frac{t}{2} \|u-u_0\|^2}{f_t(u) = f(u) + t/2 |u-u_0|^2} This function's hessian ( \eqn{f''(u)+t I} ) is positive definite for \eqn{t} sufficiently large. The value \eqn{t} is updated at every iteration: If the hessian is positive definite \eqn{t} is decreased, otherwise increased. Detailed control of the update process can be obtained with the arguments \code{ustep}, \code{power} and \code{u0}. } \seealso{ \code{\link{newtonOption}} } TMB/man/print.checkConsistency.Rd0000644000176200001440000000064714113627761016407 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/checker.R \name{print.checkConsistency} \alias{print.checkConsistency} \title{Print output from \code{\link{checkConsistency}}} \usage{ \method{print}{checkConsistency}(x, ...) } \arguments{ \item{x}{Output from \code{\link{checkConsistency}}} \item{...}{Not used} } \description{ Print diagnostics output from \code{\link{checkConsistency}} } TMB/man/print.sdreport.Rd0000644000176200001440000000061514113627761014745 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sdreport.R \name{print.sdreport} \alias{print.sdreport} \title{Print brief model summary} \usage{ \method{print}{sdreport}(x, ...) } \arguments{ \item{x}{Output from \code{\link{sdreport}}} \item{...}{Not used} } \description{ Print parameter estimates and give convergence diagnostic based on gradient and Hessian. } TMB/man/checkConsistency.Rd0000644000176200001440000000650114417511650015243 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/checker.R \name{checkConsistency} \alias{checkConsistency} \title{Check consistency and Laplace accuracy} \usage{ checkConsistency( obj, par = NULL, hessian = FALSE, estimate = FALSE, n = 100, observation.name = NULL ) } \arguments{ \item{obj}{Object from \code{MakeADFun}} \item{par}{Parameter vector (\eqn{\theta}) for simulation. If unspecified use the best encountered parameter of the object.} \item{hessian}{Calculate the hessian matrix for each replicate ?} \item{estimate}{Estimate parameters for each replicate ?} \item{n}{Number of simulations} \item{observation.name}{Optional; Name of simulated observation} } \value{ List with gradient simulations (joint and marginal) } \description{ Check consistency of various parts of a TMB implementation. Requires that user has implemented simulation code for the data and optionally random effects. (\emph{Beta version; may change without notice}) } \details{ This function checks that the simulation code of random effects and data is consistent with the implemented negative log-likelihood function. It also checks whether the approximate \emph{marginal} score function is central indicating whether the Laplace approximation is suitable for parameter estimation. Denote by \eqn{u} the random effects, \eqn{\theta} the parameters and by \eqn{x} the data. The main assumption is that the user has implemented the joint negative log likelihood \eqn{f_{\theta}(u,x)} satisfying \deqn{\int \int \exp( -f_{\theta}(u,x) ) \:du\:dx = 1} It follows that the joint and marginal score functions are central: \enumerate{ \item \eqn{E_{u,x}\left[\nabla_{\theta}f_{\theta}(u,x)\right]=0} \item \eqn{E_{x}\left[\nabla_{\theta}-\log\left( \int \exp(-f_{\theta}(u,x))\:du \right) \right]=0} } For each replicate of \eqn{u} and \eqn{x} joint and marginal gradients are calculated. Appropriate centrality tests are carried out by \code{\link{summary.checkConsistency}}. An asymptotic \eqn{\chi^2} test is used to verify the first identity. Power of this test increases with the number of simulations \code{n}. The second identity holds \emph{approximately} when replacing the marginal likelihood with its Laplace approximation. A formal test would thus fail eventually for large \code{n}. Rather, the gradient bias is transformed to parameter scale (using the estimated information matrix) to provide an estimate of parameter bias caused by the Laplace approximation. } \section{Simulation/re-estimation}{ A full simulation/re-estimation study is performed when \code{estimate=TRUE}. By default \link[stats]{nlminb} will be used to perform the minimization, and output is stored in a separate list component 'estimate' for each replicate. Should a custom optimizer be needed, it can be passed as a user function via the same argument (\code{estimate}). The function (\code{estimate}) will be called for each simulation as \code{estimate(obj)} where \code{obj} is the simulated model object. Current default corresponds to \code{estimate = function(obj) nlminb(obj$par,obj$fn,obj$gr)}. } \examples{ \dontrun{ runExample("simple") chk <- checkConsistency(obj) chk ## Get more details s <- summary(chk) s$marginal$p.value ## Laplace exact for Gaussian models } } \seealso{ \code{\link{summary.checkConsistency}}, \code{\link{print.checkConsistency}} } TMB/man/confint.tmbprofile.Rd0000644000176200001440000000101314113627761015543 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tmbprofile.R \name{confint.tmbprofile} \alias{confint.tmbprofile} \title{Profile based confidence intervals.} \usage{ \method{confint}{tmbprofile}(object, parm, level = 0.95, ...) } \arguments{ \item{object}{Output from \code{\link{tmbprofile}}.} \item{parm}{Not used} \item{level}{Confidence level.} \item{...}{Not used} } \value{ Lower and upper limit as a matrix. } \description{ Calculate confidence interval from a likelihood profile. } TMB/man/newtonOption.Rd0000644000176200001440000000075714113627761014462 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{newtonOption} \alias{newtonOption} \title{Set newton options for a model object.} \usage{ newtonOption(obj, ...) } \arguments{ \item{obj}{Object from \code{\link{MakeADFun}} for which to change settings.} \item{...}{Parameters for the \code{\link{newton}} optimizer to set.} } \value{ List of updated parameters. } \description{ Inner-problem options can be set for a model object using this function. } TMB/man/tmbprofile.Rd0000644000176200001440000000415714527235235014120 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tmbprofile.R \name{tmbprofile} \alias{tmbprofile} \title{Adaptive likelihood profiling.} \usage{ tmbprofile( obj, name, lincomb, h = 1e-04, ytol = 2, ystep = 0.1, maxit = ceiling(5 * ytol/ystep), parm.range = c(-Inf, Inf), slice = FALSE, adaptive = TRUE, trace = TRUE, ... ) } \arguments{ \item{obj}{Object from \code{MakeADFun} that has been optimized.} \item{name}{Name or index of a parameter to profile.} \item{lincomb}{Optional linear combination of parameters to profile. By default a unit vector corresponding to \code{name}.} \item{h}{Initial adaptive stepsize on parameter axis.} \item{ytol}{Adjusts the range of the likelihood values.} \item{ystep}{Adjusts the resolution of the likelihood profile.} \item{maxit}{Max number of iterations for adaptive algorithm.} \item{parm.range}{Valid parameter range.} \item{slice}{Do slicing rather than profiling?} \item{adaptive}{Logical; Use adaptive step size?} \item{trace}{Trace progress? (TRUE, or a numeric value of 1, gives basic tracing: numeric values > 1 give more information)} \item{...}{Unused} } \value{ data.frame with parameter and function values. } \description{ Calculate 1D likelihood profiles wrt. single parameters or more generally, wrt. arbitrary linear combinations of parameters (e.g. contrasts). } \details{ Given a linear combination \deqn{ t = \sum_{i=1}^n v_i \theta_i } of the parameter vector \eqn{\theta}, this function calculates the likelihood profile of \eqn{t}. By default \eqn{v} is a unit vector determined from \code{name}. Alternatively the linear combination may be given directly (\code{lincomb}). } \examples{ \dontrun{ runExample("simple",thisR=TRUE) ## Parameter names for this model: ## beta beta logsdu logsd0 ## Profile wrt. sigma0: prof <- tmbprofile(obj,"logsd0") plot(prof) confint(prof) ## Profile the difference between the beta parameters (name is optional): prof2 <- tmbprofile(obj,name="beta1 - beta2",lincomb = c(1,-1,0,0)) plot(prof2) confint(prof2) } } \seealso{ \code{\link{plot.tmbprofile}}, \code{\link{confint.tmbprofile}} } TMB/man/runSymbolicAnalysis.Rd0000644000176200001440000000100014113627761015747 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{runSymbolicAnalysis} \alias{runSymbolicAnalysis} \title{Run symbolic analysis on sparse Hessian} \usage{ runSymbolicAnalysis(obj) } \arguments{ \item{obj}{Output from \code{MakeADFun}} } \description{ Aggressively tries to reduce fill-in of sparse Cholesky factor by running a full suite of ordering algorithms. NOTE: requires a specialized installation of the package. More information is available at the package URL. } TMB/man/sdreport.Rd0000644000176200001440000001507114417511650013610 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sdreport.R \name{sdreport} \alias{sdreport} \title{General sdreport function.} \usage{ sdreport( obj, par.fixed = NULL, hessian.fixed = NULL, getJointPrecision = FALSE, bias.correct = FALSE, bias.correct.control = list(sd = FALSE, split = NULL, nsplit = NULL), ignore.parm.uncertainty = FALSE, getReportCovariance = TRUE, skip.delta.method = FALSE ) } \arguments{ \item{obj}{Object returned by \code{MakeADFun}} \item{par.fixed}{Optional. Parameter estimate (will be known to \code{obj} when an optimization has been carried out).} \item{hessian.fixed}{Optional. Hessian wrt. parameters (will be calculated from \code{obj} if missing).} \item{getJointPrecision}{Optional. Return full joint precision matrix of random effects and parameters?} \item{bias.correct}{logical indicating if bias correction should be applied} \item{bias.correct.control}{a \code{list} of bias correction options; currently \code{sd}, \code{split} and \code{nsplit} are used - see details.} \item{ignore.parm.uncertainty}{Optional. Ignore estimation variance of parameters?} \item{getReportCovariance}{Get full covariance matrix of ADREPORTed variables?} \item{skip.delta.method}{Skip the delta method? (\code{FALSE} by default)} } \value{ Object of class \code{sdreport} } \description{ After optimization of an AD model, \code{sdreport} is used to calculate standard deviations of all model parameters, including non linear functions of random effects and parameters specified through the ADREPORT() macro from the user template. } \details{ First, the Hessian wrt. the parameter vector (\eqn{\theta}) is calculated. The parameter covariance matrix is approximated by \deqn{V(\hat\theta)=-\nabla^2 l(\hat\theta)^{-1}} where \eqn{l} denotes the log likelihood function (i.e. \code{-obj$fn}). If \code{ignore.parm.uncertainty=TRUE} then the Hessian calculation is omitted and a zero-matrix is used in place of \eqn{V(\hat\theta)}. For non-random effect models the standard delta-method is used to calculate the covariance matrix of transformed parameters. Let \eqn{\phi(\theta)} denote some non-linear function of \eqn{\theta}. Then \deqn{V(\phi(\hat\theta))\approx \nabla\phi V(\hat\theta) \nabla\phi'} The covariance matrix of reported variables \eqn{V(\phi(\hat\theta))} is returned by default. This can cause high memory usage if many variables are ADREPORTed. Use \code{getReportCovariance=FALSE} to only return standard errors. In case standard deviations are not required one can completely skip the delta method using \code{skip.delta.method=TRUE}. For random effect models a generalized delta-method is used. First the joint covariance of random effect and parameter estimation error is approximated by \deqn{V \left( \begin{array}{cc} \hat u - u \cr \hat\theta - \theta \end{array} \right) \approx \left( \begin{array}{cc} H_{uu}^{-1} & 0 \cr 0 & 0 \end{array} \right) + J V(\hat\theta) J' } where \eqn{H_{uu}} denotes random effect block of the full joint Hessian of \code{obj$env$f} and \eqn{J} denotes the Jacobian of \eqn{\left( \begin{array}{cc}\hat u(\theta) \cr \theta \end{array} \right)} wrt. \eqn{\theta}. Here, the first term represents the expected conditional variance of the estimation error given the data and the second term represents the variance of the conditional mean of the estimation error given the data. Now the delta method can be applied on a general non-linear function \eqn{\phi(u,\theta)} of random effects \eqn{u} and parameters \eqn{\theta}: \deqn{V\left(\phi(\hat u,\hat\theta) - \phi(u,\theta) \right)\approx \nabla\phi V \left( \begin{array}{cc} \hat u - u \cr \hat\theta - \theta \end{array} \right) \nabla\phi'} The full joint covariance is not returned by default, because it may require large amounts of memory. It may be obtained by specifying \code{getJointPrecision=TRUE}, in which case \eqn{V \left( \begin{array}{cc} \hat u - u \cr \hat\theta - \theta \end{array} \right) ^{-1} } will be part of the output. This matrix must be manually inverted using \code{solve(jointPrecision)} in order to get the joint covariance matrix. Note, that the parameter order will follow the original order (i.e. \code{obj$env$par}). Using \eqn{\phi(\hat u,\theta)} as estimator of \eqn{\phi(u,\theta)} may result in substantial bias. This may be the case if either \eqn{\phi} is non-linear or if the distribution of \eqn{u} given \eqn{x} (data) is sufficiently non-symmetric. A generic correction is enabled with \code{bias.correct=TRUE}. It is based on the identity \deqn{E_{\theta}[\phi(u,\theta)|x] = \partial_\varepsilon\left(\log \int \exp(-f(u,\theta) + \varepsilon \phi(u,\theta))\:du\right)_{|\varepsilon=0}} stating that the conditional expectation can be written as a marginal likelihood gradient wrt. a nuisance parameter \eqn{\varepsilon}. The marginal likelihood is replaced by its Laplace approximation. If \code{bias.correct.control$sd=TRUE} the variance of the estimator is calculated using \deqn{V_{\theta}[\phi(u,\theta)|x] = \partial_\varepsilon^2\left(\log \int \exp(-f(u,\theta) + \varepsilon \phi(u,\theta))\:du\right)_{|\varepsilon=0}} A further correction is added to this variance to account for the effect of replacing \eqn{\theta} by the MLE \eqn{\hat\theta} (unless \code{ignore.parm.uncertainty=TRUE}). Bias correction can be be performed in chunks in order to reduce memory usage or in order to only bias correct a subset of variables. First option is to pass a list of indices as \code{bias.correct.control$split}. E.g. a list \code{list(1:2,3:4)} calculates the first four ADREPORTed variables in two chunks. The internal function \code{obj$env$ADreportIndex()} gives an overview of the possible indices of ADREPORTed variables. Second option is to pass the number of chunks as \code{bias.correct.control$nsplit} in which case all ADREPORTed variables are bias corrected in the specified number of chunks. Also note that \code{skip.delta.method} may be necessary when bias correcting a large number of variables. } \examples{ \dontrun{ runExample("linreg_parallel", thisR = TRUE) ## Non-random effect example sdreport(obj) } runExample("simple", thisR = TRUE) ## Random effect example rep <- sdreport(obj) summary(rep, "random") ## Only random effects summary(rep, "fixed", p.value = TRUE) ## Only non-random effects summary(rep, "report") ## Only report ## Bias correction rep <- sdreport(obj, bias.correct = TRUE) summary(rep, "report") ## Include bias correction } \seealso{ \code{\link{summary.sdreport}}, \code{\link{print.sdreport}}, \code{\link{as.list.sdreport}} } TMB/man/FreeADFun.Rd0000644000176200001440000000407214363524654013514 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{FreeADFun} \alias{FreeADFun} \title{Free memory allocated on the C++ side by \code{MakeADFun}.} \usage{ FreeADFun(obj) } \arguments{ \item{obj}{Object returned by \code{MakeADFun}} } \description{ Free memory allocated on the C++ side by \code{MakeADFun}. } \details{ An object returned by \code{MakeADFun} contains pointers to structures allocated on the C++ side. These are managed by R's garbage collector which for the most cases is sufficient. However, because the garbage collector is unaware of the C++ object sizes, it may fail to release memory to the system as frequently as necessary. In such cases one can manually call \code{FreeADFun(obj)} to release the resources. } \note{ This function is normally not needed. } \section{Memory management}{ Memory allocated on the C++ side by \code{MakeADFun} is represented by external pointers. Each such pointer has an associated 'finalizer' (see \code{reg.finalizer}) that deallocates the external pointer when \code{gc()} decides the pointer is no longer needed. Deallocated pointers are recognized on the R side as external null pointers \code{}. This is important as it provides a way to prevent the finalizers from freeing pointers that have already been deallocated \emph{even if the deallocation C-code has been unloaded}. The user DLL maintains a list of all external pointers on the C side. Three events can reduce the list: \itemize{ \item Garbage collection of an external pointer that is no longer needed (triggers corresponding finalizer). \item Explicit deallocation of external pointers using \code{FreeADFun()} (corresponding finalizers are untriggered but harmless). \item Unload/reload of the user's DLL deallocates all external pointers (corresponding finalizers are untriggered but harmless). } } \examples{ runExample("simple", thisR = TRUE) ## Create 'obj' FreeADFun(obj) ## Free external pointers obj$fn() ## Re-allocate external pointers } TMB/man/tmbroot.Rd0000644000176200001440000000410514417511650013430 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tmbroot.R \name{tmbroot} \alias{tmbroot} \title{Compute likelihood profile confidence intervals of a TMB object by root-finding} \usage{ tmbroot( obj, name, target = 0.5 * qchisq(0.95, df = 1), lincomb, parm.range = c(NA, NA), sd.range = 7, trace = FALSE, continuation = FALSE ) } \arguments{ \item{obj}{Object from \code{MakeADFun} that has been optimized.} \item{name}{Name or index of a parameter to profile.} \item{target}{desired deviation from minimum log-likelihood. Default is set to retrieve the 95% likelihood profile confidence interval, if the objective function is a negative log-likelihood function} \item{lincomb}{Optional linear combination of parameters to profile. By default a unit vector corresponding to \code{name}.} \item{parm.range}{lower and upper limits; if \code{NA}, a value will be guessed based on the parameter value and \code{sd.range}} \item{sd.range}{in the absence of explicit \code{parm.range} values, the range chosen will be the parameter value plus or minus \code{sd.range} times the corresponding standard deviation. May be specified as a two-element vector for different ranges below and above the parameter value.} \item{trace}{report information?} \item{continuation}{use continuation method, i.e. set starting parameters for non-focal parameters to solutions from previous fits?} } \value{ a two-element numeric vector containing the lower and upper limits (or \code{NA} if the target is not achieved in the range), with an attribute giving the total number of function iterations used } \description{ Compute likelihood profile confidence intervals of a TMB object by root-finding in contrast to \code{\link{tmbprofile}}, which tries to compute somewhat equally spaced values along the likelihood profile (which is useful for visualizing the shape of the likelihood surface), and then (via \code{\link{confint.tmbprofile}}) extracting a critical value by linear interpolation, } \examples{ \dontrun{ runExample("simple",thisR=TRUE) logsd0.ci <- tmbroot(obj,"logsd0") } } TMB/man/as.list.sdreport.Rd0000644000176200001440000000265314113627761015172 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sdreport.R \name{as.list.sdreport} \alias{as.list.sdreport} \title{Convert estimates to original list format.} \usage{ \method{as.list}{sdreport}(x, what = "", report = FALSE, ...) } \arguments{ \item{x}{Output from \code{\link{sdreport}}.} \item{what}{Select what to convert (Estimate / Std. Error).} \item{report}{Get AD reported variables rather than model parameters ?} \item{...}{Passed to \code{\link{summary.sdreport}}.} } \value{ List of same shape as original parameter list. } \description{ Get estimated parameters or standard errors in the same shape as the original parameter list. } \details{ This function converts the selected column \code{what} of \code{summary(x, select = c("fixed", "random"), ...)} to the same format as the original parameter list (re-ordered as the template parameter order). The argument \code{what} is partially matched among the column names of the summary table. The actual match is added as an attribute to the output. } \examples{ \dontrun{ example(sdreport) ## Estimates as a parameter list: as.list(rep, "Est") ## Std Errors in the same list format: as.list(rep, "Std") ## p-values in the same list format: as.list(rep, "Pr", p.value=TRUE) ## AD reported variables as a list: as.list(rep, "Estimate", report=TRUE) ## Bias corrected AD reported variables as a list: as.list(rep, "Est. (bias.correct)", report=TRUE) } } TMB/man/summary.checkConsistency.Rd0000644000176200001440000000102414113627761016736 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/checker.R \name{summary.checkConsistency} \alias{summary.checkConsistency} \title{Summarize output from \code{\link{checkConsistency}}} \usage{ \method{summary}{checkConsistency}(object, na.rm = FALSE, ...) } \arguments{ \item{object}{Output from \code{\link{checkConsistency}}} \item{na.rm}{Logical; Remove failed simulations ?} \item{...}{Not used} } \value{ List of diagnostics } \description{ Summarize output from \code{\link{checkConsistency}} } TMB/man/normalize.Rd0000644000176200001440000000224314113627761013747 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/normalize.R \name{normalize} \alias{normalize} \title{Normalize process likelihood using the Laplace approximation.} \usage{ normalize(obj, flag, value = 0) } \arguments{ \item{obj}{Model object from \code{MakeADFun} without proper normalization of the random effect likelihood.} \item{flag}{Flag to disable the data term from the model.} \item{value}{Value of 'flag' that signifies to not include the data term.} } \value{ Modified model object that can be passed to an optimizer. } \description{ If the random effect likelihood contribution of a model has been implemented without proper normalization (i.e. lacks the normalizing constant), then this function can perform the adjustment automatically. In order for this to work, the model must include a flag that disables the data term so that the un-normalized random effect (negative log) density is returned from the model template. Automatic process normalization may be useful if either the normalizing constant is difficult to implement, or if its calulation involves so many operations that it becomes infeasible to include in the AD machinery. } TMB/man/compile.Rd0000644000176200001440000001235014417511650013373 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{compile} \alias{compile} \title{Compile a C++ template to DLL suitable for MakeADFun.} \usage{ compile( file, flags = "", safebounds = TRUE, safeunload = TRUE, openmp = isParallelTemplate(file[1]), libtmb = TRUE, libinit = TRUE, tracesweep = FALSE, framework = getOption("tmb.ad.framework"), supernodal = FALSE, longint = FALSE, eigen.disable.warnings = TRUE, max.order = NULL, ... ) } \arguments{ \item{file}{C++ file.} \item{flags}{Character with compile flags.} \item{safebounds}{Turn on preprocessor flag for bound checking?} \item{safeunload}{Turn on preprocessor flag for safe DLL unloading?} \item{openmp}{Turn on openmp flag? Auto detected for parallel templates.} \item{libtmb}{Use precompiled TMB library if available (to speed up compilation)?} \item{libinit}{Turn on preprocessor flag to register native routines?} \item{tracesweep}{Turn on preprocessor flag to trace AD sweeps? (Silently disables \code{libtmb})} \item{framework}{Which AD framework to use ('TMBad' or 'CppAD')} \item{supernodal}{Turn on preprocessor flag to use supernodal sparse Cholesky/Inverse from system wide suitesparse library} \item{longint}{Turn on preprocessor flag to use long integers for Eigen's SparseMatrix StorageIndex} \item{eigen.disable.warnings}{Turn on preprocessor flag to disable nuisance warnings. Note that this is not allowed for code to be compiled on CRAN.} \item{max.order}{Maximum derivative order of compiler generated atomic special functions - see details.} \item{...}{Passed as Makeconf variables.} } \description{ Compile a C++ template into a shared object file. OpenMP flag is set if the template is detected to be parallel. } \details{ TMB relies on R's built in functionality to create shared libraries independent of the platform. A template is compiled by \code{compile("template.cpp")}, which will call R's makefile with appropriate preprocessor flags. Compiler and compiler flags can be stored in a configuration file. In order of precedence either via the file pointed at by R_MAKEVARS_USER or the file ~/.R/Makevars if it exists. Additional configuration variables can be set with the \code{flags} and \code{...} arguments, which will override any previous selections. } \section{Using a custom SuiteSparse installation}{ Sparse matrix calculations play an important role in TMB. By default TMB uses a small subset of \code{SuiteSparse} available through the R package \code{Matrix}. This is sufficient for most use cases, however for some very large models the following extra features are worth considering: \itemize{ \item Some large models benefit from an extended set of graph reordering algorithms (especially METIS) not part of \code{Matrix}. It is common that these orderings can provide quite big speedups. \item Some large models need sparse matrices with number of nonzeros exceeding the current 32 bit limitation of \code{Matrix}. Normally such cases will result in the cholmod error 'problem too large'. \code{SuiteSparse} includes 64 bit integer routines to address this problem. } Experimental support for linking to a \emph{custom} \code{SuiteSparse} installation is available through two arguments to the \code{\link{compile}} function. The first argument \code{supernodal=TRUE} tells TMB to use the supernodal Cholesky factorization from the system wide \code{SuiteSparse} on the C++ side. This will affect the speed of the Laplace approximation when run internally (using arguments \code{intern} or \code{integrate} to \code{\link{MakeADFun}}). The second argument \code{longint=TRUE} tells TMB to use 64 bit integers for sparse matrices on the C++ side. This works in combination with \code{supernodal=TRUE} from Eigen version 3.4. On Windows a \code{SuiteSparse} installation can be obtained using the \code{Rtools} package manager. Start 'Rtools Bash' terminal and run: \preformatted{ pacman -Sy pacman -S mingw-w64-{i686,x86_64}-suitesparse } On Linux one should look for the package \code{libsuitesparse-dev}. } \section{Selecting the AD framework}{ TMB supports two different AD libraries 'CppAD' and 'TMBad' selected via the argument \code{framework} which works as a switch to set one of two C++ preprocessor flags: 'CPPAD_FRAMEWORK' or 'TMBAD_FRAMEWORK'. The default value of \code{framework} can be set from R by \code{options("tmb.ad.framework")} or alternatively from the shell via the environment variable 'TMB_AD_FRAMEWORK'. Packages linking to TMB should set one of the two C++ preprocessor flags in Makevars. } \section{Order of compiler generated atomic functions}{ The argument \code{max.order} controls the maximum derivative order of special functions (e.g. \code{pbeta}) generated by the compiler. By default the value is set to 3 which is sufficient to obtain the Laplace approximation (order 2) and its derivatives (order 3). However, sometimes a higher value may be needed. For example \code{framework='TMBad'} allows one to calculate the Hessian of the Laplace approximation, but that requires 4th order derivatives of special functions in use. A too small value will cause the runtime error 'increase TMB_MAX_ORDER'. Note that compilation time and binary size increases with \code{max.order}. } \seealso{ \code{\link{precompile}} } TMB/man/openmp.Rd0000644000176200001440000000314514363524654013253 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{openmp} \alias{openmp} \title{Control number of OpenMP threads used by a TMB model.} \usage{ openmp(n = NULL, max = FALSE, autopar = NULL, DLL = getUserDLL()) } \arguments{ \item{n}{Requested number of threads, or \code{NULL} to just read the current value.} \item{max}{Logical; Set n to OpenMP runtime value 'omp_get_max_threads()'?} \item{autopar}{Logical; use automatic parallelization - see details.} \item{DLL}{DLL of a TMB model.} } \value{ Number of threads. } \description{ Control number of OpenMP threads used by a TMB model. } \details{ This function controls the number of parallel threads used by a TMB model compiled with OpenMP. The number of threads is part of the configuration list \code{config()} of the DLL. The value only affects parallelization of the DLL. It does \emph{not} affect BLAS/LAPACK specific parallelization which has to be specified elsewhere. When a DLL is loaded, the number of threads is set to 1 by default. To activate parallelization you have to explicitly call \code{openmp(nthreads)} after loading the DLL. Calling \code{openmp(max=TRUE)} should normally pick up the environment variable \code{OMP_NUM_THREADS}, but this may be platform dependent. An experimental option \code{autopar=TRUE} can be set to parallelize models automatically. This requires the model to be compiled with \code{framework="TMBad"} and \code{openmp=TRUE} without further requirements on the C++ code. If the C++ code already has explicit parallel constructs these will be ignored if automatic parallelization is enabled. } TMB/man/summary.sdreport.Rd0000644000176200001440000000160114417511650015276 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sdreport.R \name{summary.sdreport} \alias{summary.sdreport} \title{summary tables of model parameters} \usage{ \method{summary}{sdreport}( object, select = c("all", "fixed", "random", "report"), p.value = FALSE, ... ) } \arguments{ \item{object}{Output from \code{\link{sdreport}}} \item{select}{Parameter classes to select. Can be any subset of \code{"fixed"} (\eqn{\hat\theta}), \code{"random"} (\eqn{\hat u}) or \code{"report"} (\eqn{\phi(\hat u,\hat\theta)}) using notation as \code{\link{sdreport}}.} \item{p.value}{Add column with approximate p-values} \item{...}{Not used} } \value{ matrix } \description{ Extract parameters, random effects and reported variables along with uncertainties and optionally Chi-square statistics. Bias corrected quantities are added as additional columns if available. } TMB/man/template.Rd0000644000176200001440000000707414113627761013571 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{template} \alias{template} \title{Create cpp template to get started.} \usage{ template(file = NULL) } \arguments{ \item{file}{Optional name of cpp file.} } \description{ Create a cpp template to get started. } \details{ This function generates a C++ template with a header and include statement. Here is a brief overview of the C++ syntax used to code the objective function. For a full reference see the Doxygen documentation (more information at the package URL). Macros to read data and declare parameters: \tabular{lll}{ \bold{Template Syntax} \tab \bold{C++ type} \tab \bold{R type} \cr DATA_VECTOR(name) \tab vector \tab vector \cr DATA_MATRIX(name) \tab matrix \tab matrix \cr DATA_SCALAR(name) \tab Type \tab numeric(1) \cr DATA_INTEGER(name) \tab int \tab integer(1) \cr DATA_FACTOR(name) \tab vector \tab factor \cr DATA_IVECTOR(name) \tab vector \tab integer \cr DATA_SPARSE_MATRIX(name) \tab Eigen::SparseMatrix \tab dgTMatrix \cr DATA_ARRAY(name) \tab array \tab array \cr PARAMETER_MATRIX(name) \tab matrix \tab matrix \cr PARAMETER_VECTOR(name) \tab vector \tab vector \cr PARAMETER_ARRAY(name) \tab array \tab array \cr PARAMETER(name) \tab Type \tab numeric(1) \cr } Basic calculations: \tabular{ll}{ \bold{Template Syntax} \tab \bold{Explanation} \cr REPORT(x) \tab Report x back to R \cr ADREPORT(x) \tab Report x back to R with derivatives \cr vector v(n1); \tab R equivalent of v=numeric(n1) \cr matrix m(n1,n2); \tab R equivalent of m=matrix(0,n1,n2) \cr array a(n1,n2,n3); \tab R equivalent of a=array(0,c(n1,n2,n3)) \cr v+v,v-v,v*v,v/v \tab Pointwise binary operations \cr m*v \tab Matrix-vector multiply \cr a.col(i) \tab R equivalent of a[,,i] \cr a.col(i).col(j) \tab R equivalent of a[,j,i] \cr a(i,j,k) \tab R equivalent of a[i,j,k] \cr exp(v) \tab Pointwise math \cr m(i,j) \tab R equivalent of m[i,j] \cr v.sum() \tab R equivalent of sum(v) \cr m.transpose() \tab R equivalent of t(m) \cr } Some distributions are available as C++ templates with syntax close to R's distributions: \tabular{ll}{ \bold{Function header} \tab \bold{Distribution} \cr dnbinom2(x,mu,var,int give_log=0) \tab Negative binomial with mean and variance \cr dpois(x,lambda,int give_log=0) \tab Poisson distribution as in R \cr dlgamma(y,shape,scale,int give_log=0) \tab log-gamma distribution \cr dnorm(x,mean,sd,int give_log=0) \tab Normal distribution as in R \cr } } \examples{ template() } TMB/man/dynlib.Rd0000644000176200001440000000063114113627761013227 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{dynlib} \alias{dynlib} \title{Add dynlib extension} \usage{ dynlib(name) } \arguments{ \item{name}{Library name without extension} } \value{ Character } \description{ Add the platform dependent dynlib extension. In order for examples to work across platforms DLLs should be loaded by \code{dyn.load(dynlib("name"))}. } TMB/man/precompile.Rd0000644000176200001440000000264114417511650014104 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TMB.R \name{precompile} \alias{precompile} \title{Precompile the TMB library in order to speed up compilation of templates.} \usage{ precompile(all = TRUE, clean = FALSE, trace = TRUE, get.header = FALSE, ...) } \arguments{ \item{all}{Precompile all or just the core parts of TMB ?} \item{clean}{Remove precompiled libraries ?} \item{trace}{Trace precompilation process ?} \item{get.header}{Create files 'TMB.h' and 'TMB.cpp' in current working directory to be used as part of a project?} \item{...}{Not used.} } \description{ Precompile the TMB library } \details{ Precompilation can be used to speed up compilation of templates. It is only necessary to run \code{precompile()} once, typically right after installation of TMB. The function \emph{prepares} TMB for precompilation, while the actual pre-compilation takes place the first time you compile a model after running \code{precompile()}. Note that the precompilation requires write access to the TMB package folder. Three versions of the library will be prepared: Normal, parallel and a debugable version. Precompilation works the same way on all platforms. The only known side-effect of precompilation is that it increases the file size of the generated binaries. } \examples{ \dontrun{ ## Prepare precompilation precompile() ## Perform precompilation by running a model runExample(all = TRUE) } } TMB/man/plot.tmbprofile.Rd0000644000176200001440000000107214113627761015066 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tmbprofile.R \name{plot.tmbprofile} \alias{plot.tmbprofile} \title{Plot likelihood profile.} \usage{ \method{plot}{tmbprofile}(x, type = "l", level = 0.95, ...) } \arguments{ \item{x}{Output from \code{\link{tmbprofile}}.} \item{type}{Plot type.} \item{level}{Add horizontal and vertical lines depicting this confidence level (\code{NULL} disables the lines).} \item{...}{Additional plot arguments.} } \description{ Plot (negative log) likelihood profile with confidence interval added. } TMB/DESCRIPTION0000644000176200001440000000407714536106351012416 0ustar liggesusersPackage: TMB Type: Package Title: Template Model Builder: A General Random Effect Tool Inspired by 'ADMB' Version: 1.9.10 Date: 2023-12-12 Authors@R: c(person("Kasper","Kristensen",role=c("aut","cre","cph"),email="kaskr@dtu.dk"), person("Brad","Bell",role="cph"), person("Hans","Skaug",role="ctb"), person("Arni","Magnusson",role="ctb"), person("Casper","Berg",role="ctb"), person("Anders","Nielsen",role="ctb"), person("Martin","Maechler",role="ctb"), person("Theo","Michelot",role="ctb"), person("Mollie","Brooks",role="ctb"), person("Alex","Forrence",role="ctb"), person("Christoffer","Moesgaard Albertsen",role="ctb"), person("Cole","Monnahan",role="ctb") ) Maintainer: Kasper Kristensen Author: Kasper Kristensen [aut, cre, cph], Brad Bell [cph], Hans Skaug [ctb], Arni Magnusson [ctb], Casper Berg [ctb], Anders Nielsen [ctb], Martin Maechler [ctb], Theo Michelot [ctb], Mollie Brooks [ctb], Alex Forrence [ctb], Christoffer Moesgaard Albertsen [ctb], Cole Monnahan [ctb] Copyright: See the file COPYRIGHTS Description: With this tool, a user should be able to quickly implement complex random effect models through simple C++ templates. The package combines 'CppAD' (C++ automatic differentiation), 'Eigen' (templated matrix-vector library) and 'CHOLMOD' (sparse matrix routines available from R) to obtain an efficient implementation of the applied Laplace approximation with exact derivatives. Key features are: Automatic sparseness detection, parallelism through 'BLAS' and parallel user templates. License: GPL-2 URL: https://github.com/kaskr/adcomp/wiki BugReports: https://github.com/kaskr/adcomp/issues Depends: R (>= 3.0.0) Imports: graphics, methods, stats, utils, Matrix (>= 1.0-12) LinkingTo: Matrix, RcppEigen Suggests: numDeriv, parallel RoxygenNote: 7.2.3 NeedsCompilation: yes Packaged: 2023-12-12 14:28:28 UTC; kaskr Repository: CRAN Date/Publication: 2023-12-12 16:40:09 UTC TMB/src/0000755000176200001440000000000014531141627011467 5ustar liggesusersTMB/src/local_stubs.c0000644000176200001440000000013214113627761014145 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 #include "Matrix_stubs.c" TMB/src/solve_subset.c0000644000176200001440000003014014531117035014342 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /* ========================================================== Supernodal version of solvesubset for CHOLMOD supernodal sparse Cholesky structures. Description: * Given the factorization A=LL'. * Calculate the inverse S=A^-1 on the sparseness pattern of LL'. NOTE: In the dense case this is equivalent with "DPOTRI". Algorithm (Recursions): * s = indices of supernode * p = non-zero indices below supernode [ L(s,s) L(s,p) ] [ S(s,s) S(s,p) ] [ L(p,s) L(p,p) ] [ S(p,s) S(p,p) ] 1. S(s,p) = -L(s,s)^t^-1 * L(s,p) * S(p,p) 2. S(s,s) = -L(s,s)^t^-1 * L(s,p) * S(p,s) + (L(s,s)*L(s,s)^t)^-1 Rewritten: M0 = (L(s,s)*L(s,s)^t)^-1 (DPOTRI) M = -L(p,s) * L(s,s)^-1 (DTRSM) S(p,s) = S(p,p) * M (DSYMM) S(s,s) = M^t * S(p,s) + M0 (DGEMM) ====> IMPLEMENTATION: Compute dense submatrix Lss=L(s,s) If p not empty { 1. Compute M = -L(p,s) * L(s,s)^-1 : Compute dense submatrix M=L(p,s) M = - M * Lss^-1 DTRSM("R", "L",np,ns,-1.0,Lss,ns,M,np); 2. Compute S(p,s) = S(p,p) * M Compute dense submatrix Spp=S(p,p) 3. Compute S(s,s) = M^t * S(p,s) + M0 } M0 = (L(s,s)*L(s,s)^t)^-1 = DPOTRI("U",dims,Lss,dims,&info); ========================================================== */ #define USE_FC_LEN_T #include #include #include #ifndef FCONE # define FCONE #endif #include "Matrix.h" #include /* Copy-pasted from "Writing R Extensions". A similar spell is present in Matrix.h so might not be needed anymore ? */ #ifdef __GNUC__ // this covers gcc, clang, icc # undef alloca # define alloca(x) __builtin_alloca((x)) #elif defined(HAVE_ALLOCA_H) // needed for native compilers on Solaris and AIX # include #endif extern cholmod_common c; // See init.c /* Temporary fix until 'AS_CHM_FR__' is part of Matrix API. In future replace code below by something like: #ifdef AS_CHM_FR__ #undef AS_CHM_FR #define AS_CHM_FR AS_CHM_FR__ #endif */ #undef AS_CHM_FR #define AS_CHM_FR(x) tmb_as_cholmod_factor3((CHM_FR)alloca(sizeof(cholmod_factor)), x, FALSE) CHM_FR tmb_as_cholmod_factor3(CHM_FR ans, SEXP x, Rboolean do_check) { int *type = INTEGER(GET_SLOT(x, install("type"))); SEXP tmp; memset(ans, 0, sizeof(cholmod_factor)); /* zero the struct */ ans->itype = CHOLMOD_INT; /* characteristics of the system */ ans->dtype = CHOLMOD_DOUBLE; ans->z = (void *) NULL; ans->xtype = CHOLMOD_REAL; ans->ordering = type[0]; /* unravel the type */ ans->is_ll = (type[1] ? 1 : 0); ans->is_super = (type[2] ? 1 : 0); ans->is_monotonic = (type[3] ? 1 : 0); SEXP Matrix_permSym = install("perm"); tmp = GET_SLOT(x, Matrix_permSym); ans->minor = ans->n = LENGTH(tmp); ans->Perm = INTEGER(tmp); ans->ColCount = INTEGER(GET_SLOT(x, install("colcount"))); ans->z = ans->x = (void *) NULL; SEXP Matrix_xSym = install("x"); tmp = GET_SLOT(x, Matrix_xSym); ans->x = REAL(tmp); if (ans->is_super) { /* supernodal factorization */ ans->xsize = LENGTH(tmp); ans->maxcsize = type[4]; ans->maxesize = type[5]; ans->i = (int*)NULL; tmp = GET_SLOT(x, install("super")); ans->nsuper = LENGTH(tmp) - 1; ans->super = INTEGER(tmp); tmp = GET_SLOT(x, install("pi")); ans->pi = INTEGER(tmp); tmp = GET_SLOT(x, install("px")); ans->px = INTEGER(tmp); tmp = GET_SLOT(x, install("s")); ans->ssize = LENGTH(tmp); ans->s = INTEGER(tmp); } else { Rf_error("Unexpected"); } return ans; } SEXP tmb_destructive_CHM_update(SEXP L, SEXP H, SEXP mult) { CHM_FR f = AS_CHM_FR(L); CHM_SP A = AS_CHM_SP__(H); double mm[2] = {0, 0}; mm[0] = asReal(mult); // NB: Result depends if A is "dsC" or "dgC"; the latter case assumes we mean AA' !!! /* cholmod_factorize_p return value: TRUE: CHOLMOD_OK, CHOLMOD_NOT_POSDEF, CHOLMOD_DSMALL FALSE: CHOLMOD_NOT_INSTALLED, CHOLMOD_OUT_OF_MEMORY, CHOLMOD_TOO_LARGE, CHOLMOD_INVALID, CHOLMOD_GPU_PROBLEM */ if (!M_cholmod_factorize_p(A, mm, (int*)NULL, 0 /*fsize*/, f, &c)) /* -> ./CHOLMOD/Cholesky/cholmod_factorize.c */ error("cholmod_factorize_p failed: status %d, minor %lu of ncol %lu", (int) c.status, (unsigned long) f->minor, (unsigned long) f->n); int ok = (f->minor == f->n); // WAS: (c.status == CHOLMOD_OK); return ScalarLogical(ok); } SEXP tmb_CHMfactor_solve(SEXP L_, SEXP y_) { CHM_FR L = AS_CHM_FR(L_); int n = LENGTH(y_); CHM_DN y = N_AS_CHM_DN(REAL(y_), n, 1); SEXP x = PROTECT( NEW_NUMERIC( n ) ); CHM_DN sol = M_cholmod_solve(CHOLMOD_A, L, y, &c); memcpy(REAL(x), sol->x, n * sizeof(double)); M_cholmod_free_dense(&sol, &c); UNPROTECT(1); return x; } // Notes about the CHOLMOD super-nodal storage. // According to the documentation of CHOLMOD we have: // ================================================== // k1 = Super [s] ; /* s contains columns k1 to k2-1 of L */ // k2 = Super [s+1] ; // nscol = k2 - k1 ; /* # of columns in all of s */ // psi = Lpi [s] ; /* pointer to first row of s in Ls */ // psx = Lpx [s] ; /* pointer to first row of s in Lx */ // psend = Lpi [s+1] ; /* pointer just past last row of s in Ls */ // nsrow = psend - psi ; /* # of rows in all of s */ // * See discussion in cholmod_change_factor.c: // * (3) supernodal symbolic: A representation of the nonzero pattern of the // * supernodes for a supernodal factorization. There are L->nsuper // * supernodes. Columns L->super [k] to L->super [k+1]-1 are in the kth // * supernode. The row indices for the kth supernode are in // * L->s [L->pi [k] ... L->pi [k+1]-1]. The numerical values are not // * allocated (L->x), but when they are they will be located in // * L->x [L->px [k] ... L->px [k+1]-1], and the L->px array is defined // * in this factor type. /* Extract dense block x[p,q] of sparse matrix x */ CHM_DN densesubmatrix(CHM_SP x, int *p, int np, int *q, int nq, cholmod_common *c){ CHM_DN ans = M_cholmod_allocate_dense(np,nq,np,CHOLMOD_REAL,c); double *w = malloc(x->nrow*sizeof(double)); int *xi=x->i; int *xp=x->p; double *xx=x->x; double *ansx=ans->x; int col, row; for(int j=0;jsuper; int* Ls=L->s; int* Lpi=L->pi; int ncol=super[k+1]-super[k]; /* ncol of supernode */ int nrow=Lpi[k+1]-Lpi[k]; /* Number of rows in supernode */ /* q contains row-indices of *entire* supernode */ /* p contains row-indices excluding those of diagonal */ /* s contains row-indices of diagonal - setdiff(q,p) */ int* q=Ls+Lpi[k]; /* Pointer to L->s [L->pi [k]] */ int nq=nrow; /* length of q */ // int* p=q+ncol; /* Exclude triangle in diagonal */ int np=nq-ncol; /* length of p */ int* s=q; int ns=ncol; /* length of s */ /* do not sort because p is sorted */ int info; /* For lapack */ int i,j; double ONE=1.0, ZERO=0.0, MONE=-1.0; CHM_DN x = densesubmatrix(Lsparse,q,nq,q,nq,c); double *xx=x->x; double *Lss=xx, *Lps=xx+ns, *Ssp=xx+(nq*ns), *Spp=xx+(nq*ns+ns); /* Workspace to hold output from dsymm */ double *wrk=malloc(nq*ns*sizeof(double)); double *wrkps=wrk+ns; if(np>0){ F77_CALL(dtrsm)("R", "L", "N", "N", &np, &ns, &MONE, Lss, &nq, Lps, &nq FCONE FCONE FCONE FCONE); for(i=ns;ix; int *Lp=Lsparse->p; int m=Lp[s[0]]; for(j=0;j0){ */ /* flopcount[0]+=(Ns*(Ns+1))*0.5*Np; /\* dtrsm *\/ */ /* flopcount[1]+=Np*Np*Ns; /\* dsymm *\/ */ /* flopcount[2]+=2.0*(Ns*Ns*Ns)/3.0; /\* dpotri *\/ */ /* flopcount[3]+=Ns*Np*Ns; /\* dgemm *\/ */ /* } else { */ /* flopcount[2]+=2.0*(Ns*Ns*Ns)/3.0; /\* dpotri *\/ */ /* } */ /* } */ /* Clean up */ M_cholmod_free_dense(&x,c); free(wrk); } CHM_SP tmb_inv_super(CHM_FR Lfac, cholmod_common *c){ /* Convert factor to sparse without modifying factor */ CHM_FR Ltmp = M_cholmod_copy_factor(Lfac,c); CHM_SP L = M_cholmod_factor_to_sparse(Ltmp,c); M_cholmod_free_factor(&Ltmp,c); /* Loop over supernodes */ int nsuper=Lfac->nsuper; for(int k=nsuper-1;k>=0;k--)tmb_recursion_super(L,k,Lfac,c); /* Change to symm lower */ L->stype=-1; return L; } SEXP tmb_invQ(SEXP Lfac){ CHM_FR L=AS_CHM_FR(Lfac); CHM_SP iQ = tmb_inv_super(L, &c); return M_chm_sparse_to_SEXP(iQ, 1 /* Free */ , 0, 0, "N" /* Not unit */, R_NilValue); } void half_diag(CHM_SP A){ int ncol=A->ncol; double *Ax; int *Ai, *Ap, i; Ai=A->i; Ap=A->p; Ax=A->x; for(int j=0;jstype=0; /* Change to non-sym */ return M_chm_sparse_to_SEXP(iQ, 1 /* Free */ , -1 /* uplo="L" */ , 0, "N" /* Not unit */, R_NilValue); } /* Given sparse matrices A and B (sorted columns). Assume pattern of A is a subset of pattern of B. (This also includes cases where dimension of B larger than dim of A) Return integer vector p of same length as A@x such that " A@i == B@i[p] and A@j == B@j[p] " */ SEXP match_pattern(SEXP A_, SEXP B_){ CHM_SP A=AS_CHM_SP(A_); CHM_SP B=AS_CHM_SP(B_); int *Ai=A->i, *Bi=B->i, *Ap=A->p, *Bp=B->p; int ncol=A->ncol,i,j,k; int index; // index match SEXP ans; if(A->ncol>B->ncol)error("Must have dim(A)<=dim(B)"); PROTECT(ans=NEW_INTEGER(A->nzmax)); int *pans=INTEGER(ans); for(j=0;j=Bp[j+1]){ UNPROTECT(1); error("No match"); } } *pans=index+1; pans++; // R-index ! } } UNPROTECT(1); return ans; } /* Sparse version of 'insert zeros and modify diagonal' ( izamd ) keeping the sparsity pattern un-modified: A[:,p] <- 0; A[p,:] <- 0; diag(A)[p] <- d; A_ : Sparse matrix to modify mark_ : Logical (int) index vector of rows and columns. diag_ : Diagonal replacement (double). */ SEXP tmb_sparse_izamd(SEXP A_, SEXP mark_, SEXP diag_){ CHM_SP A = AS_CHM_SP(A_); int *Ai=A->i, *Ap=A->p; double *Ax = A->x; int ncol=A->ncol; int *mark = INTEGER(mark_); double diag = REAL(diag_)[0]; int i, l=0; for(int j = 0; j < ncol; j++){ for(int k = Ap[j]; k < Ap[j+1]; k++){ i = Ai[k]; if (mark[i]) Ax[l] = 0; if (mark[j]) Ax[l] = 0; if ( (mark[i] || mark[j]) && (i == j) ) Ax[l] = diag; l++; } } return A_; } /* Half the diagonal of a matrix (note: modifies input) */ SEXP tmb_half_diag(SEXP A_){ CHM_SP A = AS_CHM_SP(A_); half_diag(A); return A_; } TMB/src/init.c0000644000176200001440000000251514363524654012611 0ustar liggesusers#include #include #include #include "Matrix.h" cholmod_common c; #define CALLDEF(name, n) {#name, (DL_FUNC) &name, n} SEXP omp_num_threads(SEXP x); SEXP isNullPointer(SEXP pointer); SEXP setxslot(SEXP x, SEXP y); SEXP tmb_invQ(SEXP Lfac); SEXP tmb_invQ_tril_halfdiag(SEXP Lfac); SEXP match_pattern(SEXP A_, SEXP B_); SEXP tmb_sparse_izamd(SEXP A_, SEXP mark_, SEXP diag_); SEXP tmb_half_diag(SEXP A_); SEXP have_tmb_symbolic(void); SEXP tmb_symbolic(SEXP Qp); SEXP tmb_destructive_CHM_update(SEXP L, SEXP H, SEXP mult); SEXP tmb_CHMfactor_solve(SEXP L_, SEXP y_); static R_CallMethodDef CallEntries[] = { CALLDEF(omp_num_threads, 1), CALLDEF(isNullPointer, 1), CALLDEF(setxslot, 2), CALLDEF(tmb_invQ, 1), CALLDEF(tmb_invQ_tril_halfdiag, 1), CALLDEF(match_pattern, 2), CALLDEF(tmb_sparse_izamd, 3), CALLDEF(tmb_half_diag, 1), CALLDEF(have_tmb_symbolic, 0), CALLDEF(tmb_symbolic, 1), CALLDEF(tmb_destructive_CHM_update, 3), CALLDEF(tmb_CHMfactor_solve, 2), {NULL, NULL, 0} }; void R_init_TMB(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, (Rboolean)FALSE); M_R_cholmod_start(&c); c.error_handler = NULL; // Disable CHOLMOD warnings } void R_unload_TMB(DllInfo *dll) { M_cholmod_finish(&c); } TMB/src/external_metis.c0000644000176200001440000000645014363524654014673 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 #include #include #include #include "Matrix.h" #include #ifdef _USE_EXTERNAL_CHOLMOD_LIB_ /* ========================================================================== */ /* Error handler */ /* ========================================================================== */ void tmb_cholmod_error(int status, const char *file, int line, const char *message) { /* From CHOLMOD/Include/cholmod_core.h : ...status values. zero means success, negative means a fatal error, positive is a warning. */ warning(("Cholmod warning '%s' at file:%s, line %d"), message, file, line); } cholmod_factor *cholmod_analyze ( /* ---- input ---- */ cholmod_sparse *A, /* matrix to order and analyze */ /* --------------- */ cholmod_common *Common ) ; int cholmod_free_factor ( /* ---- in/out --- */ cholmod_factor **LHandle, /* factor to free, NULL on output */ /* --------------- */ cholmod_common *Common ) ; /* ========================================================================== */ /* Run the symbolic analysis and prepare workspace - only run once !!! */ /* ========================================================================== */ SEXP tmb_symbolic(SEXP Qp){ cholmod_common c; M_R_cholmod_start(&c); /* TODO: More control from R */ c.nmethods=9; c.supernodal = CHOLMOD_SUPERNODAL; c.final_ll = TRUE; /* Return quickly if not positive definite */ c.quick_return_if_not_posdef=TRUE; c.error_handler=tmb_cholmod_error; int trace=1; CHM_SP Q = M_cholmod_copy(AS_CHM_SP(Qp), -1 /* symmetric lower */, 1 /*values*/, &c); CHM_FR LQ; CHM_FR LQ2; // Step 1: Run symbolic analysis with external cholmod library: if(trace)Rprintf("Entering externallib \n"); c.itype=CHOLMOD_INT; LQ = cholmod_analyze(Q, &c); /* get fill-reducing permutation */ if(trace)Rprintf("cholmod_analyze: status=%d \n",c.status); if(trace)Rprintf("Chosen ordering %d \n", c.selected); // Step 2: Grab the permutation: int *perm=LQ->Perm; // Step 3: Run symbolic analysis again, now with known permutation // using the R cholmod interface routines if(trace)Rprintf("Running symbolic analysis \n"); if(trace)Rprintf("User permutation \n"); c.nmethods=1; LQ2 = M_cholmod_analyze_p(Q, perm, NULL, 0, &c); cholmod_free_factor(&LQ,&c); // LQ Not needed anymore if(trace)Rprintf("Chosen ordering %d \n", c.selected); if(trace)Rprintf("Length of supernodal xslot %d \n", LQ2->xsize); if(trace)Rprintf("Flopcount %f \n", c.fl); double nnzL = LQ2->xsize; double nnzQ = Q->nzmax; if(trace)Rprintf("Fill-in ratio (nnz(L)/nnz(Q)) %f \n", nnzL/nnzQ); if(trace)Rprintf("Factor xtype %d \n", LQ2->xtype); // Step 4: Make sure factor has numerical values if(trace)Rprintf("Running numerical factorization \n"); M_cholmod_factorize(Q, LQ2, &c); if(trace)Rprintf("Done \n"); // Cleanup M_cholmod_free_sparse(&Q,&c); M_cholmod_finish(&c); return M_chm_factor_to_SEXP(LQ2, 1 /* Free */); } #else SEXP tmb_symbolic(SEXP Qp) { return R_NilValue; } #endif SEXP have_tmb_symbolic(void) { SEXP ans; PROTECT(ans = NEW_INTEGER(1)); #ifdef _USE_EXTERNAL_CHOLMOD_LIB_ INTEGER(ans)[0]=1; #else INTEGER(ans)[0]=0; #endif UNPROTECT(1); return ans; } TMB/src/utils.c0000644000176200001440000000131514115433340012765 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 # ifdef _OPENMP #include # endif # include # include /* openmp controller */ SEXP omp_num_threads(SEXP x) { #ifdef _OPENMP if( !isNull(x) ){ int n = INTEGER(x)[0]; omp_set_num_threads( n ); } return ScalarInteger( omp_get_max_threads() ); #else warning("OpenMP not supported."); return ScalarInteger( 0 ); #endif } /* Avoid S4 overhead when changing x-slot: Set xslot to SEXP pointer i.e. x@x <- y */ SEXP setxslot(SEXP x, SEXP y){ setAttrib(x,install("x"),y); return x; } /* Is external pointer nil ? */ SEXP isNullPointer(SEXP pointer) { return ScalarLogical(!R_ExternalPtrAddr(pointer)); } TMB/src/Makevars0000644000176200001440000000015314536067012013162 0ustar liggesusersPKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) $(SHLIB_OPENMP_CFLAGS) PKG_CFLAGS = $(SHLIB_OPENMP_CFLAGS) TMB/NEWS0000644000176200001440000005363414536066764011427 0ustar liggesusers------------------------------------------------------------------------ TMB 1.9.10 (2023-12-12) ------------------------------------------------------------------------ o precompile(): Translation unit changes that should not be visible to the user. ------------------------------------------------------------------------ TMB 1.9.9 (2023-11-27) ------------------------------------------------------------------------ o Fix 'Wformat' warnings ------------------------------------------------------------------------ TMB 1.9.7 (2023-11-22) ------------------------------------------------------------------------ o Fixed tweedie integer overflow for extreme parameters. o Added new argument 'adaptive' to 'tmbprofile'. o Added new atomic matrix functions 'sqrtm' and 'absm'. o Avoid unnecessary warnings on 'Matrix package version inconsistency'. ------------------------------------------------------------------------ TMB 1.9.6 (2023-08-11) ------------------------------------------------------------------------ o Fix UBSAN observed for nested AD contexts. ------------------------------------------------------------------------ TMB 1.9.5 (2023-07-18) ------------------------------------------------------------------------ o R: Prepare determinant() change from Matrix version 1.6-0. o R: oneStepPredict() now allows mixed discrete/continuous distributions. o C++: New atomic 'fft'. ------------------------------------------------------------------------ TMB 1.9.4 (2023-04-18) ------------------------------------------------------------------------ o Fix internal bug causing wrong 'sparse_matrix_exponential' derivatives. o Prepare for upcoming Matrix_1.5-5 (Fix misuse of Matrix C-API). ------------------------------------------------------------------------ TMB 1.9.3 (2023-03-28) ------------------------------------------------------------------------ o Prepare for Matrix 1.5-4 deprecations. o checkConsistency(): New argument 'estimate' enables full simulation study and another argument 'observation.name' can be used to not retape between simulation replicates. o oneStepPredict(): Eliminate nuisance warnings from generic method. o C++ side: Added preprocessor flag 'TMB_ABORT' to better control behaviour in 'TMB_SAFEBOUNDS' mode (e.g. signal normal R error rather than abort). In addition, 'TMB_CATCH' can now be configured to catch more than just std::bad_alloc. ------------------------------------------------------------------------ TMB 1.9.2 (2023-01-23) ------------------------------------------------------------------------ o Improved interoperability with Rcpp (conflicts resolved). o Fix some broken sparse matrix coercions that used to work. o New features on C++ side: - Atomic sparse matrix exponential. - Atomic vectorized operations mainly for internal use. - Faster matrix multiply for higher order AD (see example 'hmm_filter'). - Utility for parameter object concatenation. o Fix warnings from CRAN check page. ------------------------------------------------------------------------ TMB 1.9.1 (2022-08-16) ------------------------------------------------------------------------ o Prepare for Matrix 1.4-2 deprecations. o Fix html version of sdreport docs (thanks to Kurt Hornik). o Constant input test was missing for some special functions. o Added argument 'max.order' to compile(). o oneStepPredict() CDF method was stabilized. o 2D interpolation operator was added on C++ side. ------------------------------------------------------------------------ TMB 1.9.0 (2022-05-26) ------------------------------------------------------------------------ o Fix PROTECT bugs (thanks to Tomas Kalibera) o Behavior if TMB parallization has been changed: - Setting the number of threads of a TMB model using TMB::openmp() is now portable across platforms. - Number of TMB threads no longer interferes with number of threads used by other packages or BLAS/LAPACK. - By default, unless explicitly requested, models run with a single thread. o precompile() can now auto generate 'TMB.h' and 'TMB.cpp' that may be used by R packages to split in several compilation units. o MakeADFun() now checks that the DLL is loaded. ------------------------------------------------------------------------ TMB 1.8.1 (2022-03-23) ------------------------------------------------------------------------ o Fix some clang-14 compiler warnings. ------------------------------------------------------------------------ TMB 1.8.0 (2022-03-07) ------------------------------------------------------------------------ o Experimental support for new AD library 'TMBad' - see ?compile. o Option to discard nuisance warnings from Eigen - see ?compile. ------------------------------------------------------------------------ TMB 1.7.22 (2021-09-28) ------------------------------------------------------------------------ o Fortran character strings: use 'FCONE' macro o Add .onUnload() (GH #353) o Fix tmbutils::array ASAN issue triggered by at least clang-13 ------------------------------------------------------------------------ TMB 1.7.21 (2021-09-06) ------------------------------------------------------------------------ o Fix CRAN build issue triggered by clang 13.0.0 (omp.h) o Fix tweedie thread safety on Windows (https://github.com/glmmTMB/glmmTMB/issues/714) o Fix as.list(.) for class 'sdreport' (https://github.com/glmmTMB/glmmTMB/issues/692) ------------------------------------------------------------------------ TMB 1.7.20 (2021-04-08) ------------------------------------------------------------------------ o Make parList() work in more edge cases. o Make tiny_ad variables work (again) with Eigen types. o Avoid header issues in Matrix 1.3-0 due to SuiteSparse update (#340) ------------------------------------------------------------------------ TMB 1.7.19 (2021-02-05) ------------------------------------------------------------------------ o 'sdreport()' failed in a special case (GH #333) o Improved implementation of 'rtweedie()' o Fixed thread safety issues (GH #330) o Fixed 'tmbroot()' and 'tmbprofile()' for single-parameter models o Function 'compile()' now quotes more paths (GH #323) ------------------------------------------------------------------------ TMB 1.7.18 (2020-07-24) ------------------------------------------------------------------------ o Fix clang-ASAN issue caused by memory management changes ------------------------------------------------------------------------ TMB 1.7.17 (2020-07-23) ------------------------------------------------------------------------ o New function 'FreeADFun()' gives the user more control with memory deallocation. In addition memory management of external pointers have been improved - see '?FreeADFun'. o Documentation errors in '?sdreport' have been corrected. o The function 'oneStepPredict()' now calculates residuals in reverse order because it is more stable. Old behaviour can be obtained by passing 'reverse=FALSE'. ------------------------------------------------------------------------ TMB 1.7.16 (2020-01-15) ------------------------------------------------------------------------ o Fixed memory leaks in sparse hessian. o logspace_add: Added some edge case reductions. o 'oneStepPredict' no longer overwrites mapping of random effects. o Fix isfinite, isinf, isnan etc (github #297). o Add support for other object names to 'gdbsource'. o dbinom: Handle edge cases 0*log(0). o Add segment method to vector_indicator. o data_indicator: Add default CTOR. o splinefun: fix memleak + add vector evaluation. o Saved models from old TMB versions should now be usable in new TMB versions without giving the INTEGER(...) error. o checkConsistency bugfix: did not work for mapped random effects. ------------------------------------------------------------------------ TMB 1.7.15 (2018-11-08) ------------------------------------------------------------------------ o Allow report array of any type (similar to vector case) o Solve 'rck' issue from CRAN o Fix bug in separable simulate ------------------------------------------------------------------------ TMB 1.7.14 (2018-06-23) ------------------------------------------------------------------------ o Fix performance bug triggered by R-devel. o Fixed bug in sparsity detection algorithm. o Tweedie atomic function speedup. o Fix save/reload model object. Loaded object no longer overwrites fitted parameters when running e.g. obj$report() or obj$simulate(). o New function 'tmbroot' computes likelihood profile confidence intervals. ------------------------------------------------------------------------ TMB 1.7.13 (2018-03-22) ------------------------------------------------------------------------ o Redundant warnings from CHOLMOD have been silenced. o ADREPORT now tracks object dimensions. More infomation in '?TMB::as.list.sdreport'. o New feature to do process normalization from R. See '?TMB::normalize'. o New feature to update data from R without re-taping the computational graph. Enabled on C++ side using 'DATA_UPDATE'. o bugfix C++ namespace 'autodiff': Jacobian had wrong dimension. ------------------------------------------------------------------------ TMB 1.7.12 (2017-12-10) ------------------------------------------------------------------------ o Fix CRAN rchk tool warnings (although false alarm) o New macro TMB_OBJECTIVE_PTR for more flexible use of DATA and PARAMETER objects. o Fix 'oneStepPredict' when no random effects. o C callable routines 'tmb_forward' and 'tmb_reverse' added. o Fix bug in empty array assignment. o Fix slow 'oneStepPredict' caused by matrix inversion in 'tmbprofile'. o TMB:::setupRstudio() o compile: Add flag for tracing forward sweeps. ------------------------------------------------------------------------ TMB 1.7.11 (2017-08-09) ------------------------------------------------------------------------ o Allow logical data objects o Fix conversion R <-> C++ of long objects - Can now pass long vector (length >= 2^31) as DATA_VECTOR. - Can now REPORT a long vector. - Can now calculate long jacobian matrices (m*n can be greater than 2^31 where n is the number of parameters and m the number of ADREPORTed variables). o Fixed a possible segmentation fault in sparsity detection algorithm. o New flag to sdreport() reduces memory usage when bias correcting a large number of variables. o New experimental function checkConsistency() to check the Laplace approximation and correctness of the user template. ------------------------------------------------------------------------ TMB 1.7.10 (2017-05-03) ------------------------------------------------------------------------ o Fix broken Solaris build caused by Eigen 3.3.3 update ------------------------------------------------------------------------ TMB 1.7.9 (2017-04-12) ------------------------------------------------------------------------ o Fix PROTECT bugs reported by Tomas Kalibera. o Now possible to use 'autodiff::hessian' in conjunction with atomic functions. o Fix 'testthat:::expect_equal(obj, obj)' crash for non-random effect models. o Fix compatibility issues of 'tmbutils::vector' with eigen 3.3.2. ------------------------------------------------------------------------ TMB 1.7.8 (2017-02-08) ------------------------------------------------------------------------ o Internal bug fixes. - Fix bug in GMRF constructor from grid array. - Fix printing of Eigen/AD types (broken by version 1.7.7) ------------------------------------------------------------------------ TMB 1.7.7 (2017-01-31) ------------------------------------------------------------------------ o Internal modifications: - Fix Eigen 3.3.2 compatibility issues. - Disable dynamic symbols. ------------------------------------------------------------------------ TMB 1.7.6 (2017-01-15) ------------------------------------------------------------------------ o Add Conway-Maxwell-Poisson distribution (dcompois, rcompois). o Add lfactorial. o Move MCMC to separate package. o Add simulators for exponential, beta, F, logistic, Student T, and Weibull distributions. o Fix a bug in function 'split'. ------------------------------------------------------------------------ TMB 1.7.5 (2016-11-20) ------------------------------------------------------------------------ o Atomic logspace_add and logspace_sub. o Numerically robust binomial and negative binomial density functions. o New macros: - DATA_STRING to pass strings from R. - SIMULATE to mark blocks of simulation code. o Simulation methods implemented for density classes: - MVNORM, AR1, SCALE, VECSCALE, SEPARABLE, GMRF, ARk. o R-style simulators now available from the template: - rnorm, runif, rpois, rbinom, rgamma, rnbinom and rnbinom2. ------------------------------------------------------------------------ TMB 1.7.4 (2016-09-21) ------------------------------------------------------------------------ o Add onLoad check on 'Matrix' package version. o runExample: Fixed bug when running all examples from a specified example folder. o sdreport: Fixed bug in the case with exactly one random effect. o sdreport: Reduced size of output. ------------------------------------------------------------------------ TMB 1.7.3 (2016-09-05) ------------------------------------------------------------------------ o New atomic functions: - pbeta - qbeta - dtweedie - besselK (derivatives wrt both arguments) - besselI (derivatives wrt both arguments) - besselJ (derivatives wrt both arguments) - besselY (derivatives wrt both arguments) o Adaptive numerical integration: - gauss_kronrod::integrate (one dimension) - gauss_kronrod::mvIntegrate (multiple dimensions) o sdreport: Fix bug that caused bias.correction to break when parameter maps were in use. ------------------------------------------------------------------------ TMB 1.7.2 (2016-08-09) ------------------------------------------------------------------------ o sdreport: Allow bias correct in chunks to reduce memory. o Experimental TMB:::install.contrib to install user contributed cpp code from github. o Disable CHOLMOD warnings from inner problem when silent=TRUE. o sdreport: Keep running when solve(hessian) fails. o sdreport: Fix bug that caused summary(sdreport(.)) to fail when nothing was ADREPORTed. ------------------------------------------------------------------------ TMB 1.7.1 (2016-05-05) ------------------------------------------------------------------------ o Lots of minor performance optimizations. o sdreport: New argument getReportCovariance. - Reduces memory usage when many variables are ADREPORTed. o bugfix: numeric(0) in random list of MakeADFun caused wrong parameter list. o New atomic: convol2d ------------------------------------------------------------------------ TMB 1.7.0 (2016-03-22) ------------------------------------------------------------------------ o CITATION update with JSS publication. o New function 'as.list.sdreport' converts from sdreport format to original parameter list structure. o MCMC: - Fix small bug in transforming intial values in NUTS. - Rename mcmc -> run_mcmc to avoid conflict with coda package. ------------------------------------------------------------------------ TMB 1.6.6 (2016-01-28) ------------------------------------------------------------------------ o oneStepPredict: Add one-step mean to output for methods 'oneStepGaussianOffMode' and 'oneStepGeneric'. o Array class changes: - More explicit array assignment from other class: Can now assign from matrix and un-evaluated expression template E.g. a = a.matrix() * a.matrix(); - Documentation: warning about the 2D case - Re-implement vec() operator (avoid loop) - Add method matrix() to array class: Keeps first dimension and collapses remaining dimensions. o Clean up potential naming conflicts caused by Rmath macros o Atomic functions general speedup o bugfix: precompile broke REGISTER_ATOMIC ------------------------------------------------------------------------ TMB 1.6.5 (2015-12-02) ------------------------------------------------------------------------ o Fix bug that caused sdreport to fail for models using the 'profile' argument to MakeADFun. o Robustify marginal likelihood for extreme parameters (to help MCMC). o MCMC: Improved stability of adaptive step size algorithm. o Bias correction documentation and test example. Results are now part of the summary output. ------------------------------------------------------------------------ TMB 1.6.4 (2015-11-22) ------------------------------------------------------------------------ o precompile() makeover: - Works on all platforms. - Works with multiple models in same R instance. - Frequently used classes MVNORM_t and GMRF_t added to precompilation. ------------------------------------------------------------------------ TMB 1.6.3 (2015-11-11) ------------------------------------------------------------------------ o Fix array rows() method (The method inherited from Eigen would report the length of the underlying vector). o Eliminate std::cout in CRAN version. o MCMC samplers (HMC, NUTS and RWM) added by Cole Monnahan. ------------------------------------------------------------------------ TMB 1.6.0 (2015-10-08) ------------------------------------------------------------------------ o Major changeset to get closer to CRAN submission - Added 'dontrun' to most examples. Reason: All useful TMB examples take too long time to run because they require compilation. - Removed TMB-internals. - Added Roxygen for remaining functions: dynlib() runSymbolicAnalysis() config() plot.parallelBenchmark() summary.sdreport() print.sdreport() print.backtrace() plot.tmbprofile() confint.tmbprofile() - Got rid of global configuration, e.g flagsDefaults(), newtonDefaults() etc. - Reworked newtonOption() and adapted all examples to new syntax. (NOTE: not entirely backwards compatible since to old version modified global settings, which we do not allow anymore). - Fixed several typos, e.g. c++ -> C++ - CITATION: Added arxiv reference. - DESCRIPTION: Changed title and added URL. - NAMESPACE: Cleanup o CppAD jacobian: prefer reverse mode over forward mode if work is equal - TMB only requires 1st order reverse (not forward) mode to be implemented for atomic functions. This can result in the error 'order not implemented' if CppAD automatically selects forward over reverse mode. - In cases where the work of forward and reverse mode are equal it is therefore more natural (from TMB perspective) to select reverse mode. o Document parallel_accumulator #122 o Lots of doxygen documentation updates ------------------------------------------------------------------------ TMB 1.5-1 (2015-10-04) ------------------------------------------------------------------------ o From now on the github version follows the R version o Added NEWS file o Emacs mode version 3.0 from Arni Magnusson o Robustify tmbprofile() #137 o Experimental oneStepPredict() now handles discrete case as part of a general 'oneStepGeneric' method. o tmbprofile() multiple changes - Allow specification of a valid range of the parameter. - Get more detail in the center of the distribution. (does not affect cases where likelihood has been optimized) o C++: New namespace 'autodiff' makes it easy to use AD from the user template. o C++: New namespace 'romberg' with wrappers around CppAD integration routines. o Automatic retape when loading saved ADFun objects. o Keep attribute 'check.passed' when subsetting parameter list o Fix 32 bit o match pattern: Improvement for large problems. As a result it is now be possible to handle 2^31-1 nonzeros in Cholesky factor. Old method would break down around 2^30. o MVNORM_t: Method to evaluate marginals. o oneStepPredict() now works with maps #108. o Lots of improvements and cleanups from Martin Maechler. ------------------------------------------------------------------------ TMB 1.5-0 (2015-08-10) ------------------------------------------------------------------------ o Add pnorm/qnorm one-argument vectorized versions. o bugfix: Vectorized math operations crashed in the zero-length case. o Add missing bounds check to array class #100 - Now checks each index component (not just the re-mapped univariate index). o BesselK atomic + Matern correlation function. o asSparseMatrix and asSparseVector fix: Conversion from dense to sparse should not drop zero-entries that could potentially become nonzero (i.e. parameter dependent entries). o CppAD::Variable now works for TMB models. o Script to enable 'runSymbolicAnalysis' on all Linux and OS X systems. o New experimental function 'oneStepPredict' for OSA residuals with ar1xar1 as an example. o New atomic function 'ppois'. o REPORT: Allow report vector of 'anything'. o getUserDLL: Improve guess of user's DLL code (when DLL not given to MakeADFun). o Eliminate warning with '-Wpedantic'. o sdreport new option: ignore.parm.uncertainty. o New example: HMM filter. o General 1D likelihood profile function + method to get profile confidence intervals + plot method. o MakeADFun: New option to move outer parameters to the inner problem (purpose: get same speed as the REML trick for linear fixed effects without loosing the ML interpretation). o MakeADFun: New argument 'silent' to disable all tracing output. ------------------------------------------------------------------------ TMB 1.4-0 (2015-04-16) ------------------------------------------------------------------------ o CppAD updated to development version. Reduced peak memory usage with up to 50% for large models. o New configuration variables. o Avoid crashes due to memory allocation errors. o Print index errors to error stream. o Allow compilation with -std=c++11. o sdreport: bias.correct optimizations. o Implement up to 7d array (like admb). o Allow lists as data object with R-inla SPDE structures as an example. ------------------------------------------------------------------------ TMB 1.0-0 (2013-09-10) ------------------------------------------------------------------------ o Initial release. TMB/R/0000755000176200001440000000000014536066764011116 5ustar liggesusersTMB/R/gdbsource.R0000644000176200001440000000617114527235235013212 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ##' Source R-script through gdb to get backtrace. ##' ##' This function is useful for debugging templates. ##' If a script aborts e.g. due to an out-of-bound index operation ##' it should be fast to locate the line that caused the problem by ##' running \code{gdbsource(file)}. ##' Alternatively, If more detailed debugging is required, then ##' \code{gdbsource(file,TRUE)} will provide the full backtrace followed ##' by an interactive gdb session where the individual frames can be inspected. ##' Note that templates should be compiled without optimization and with debug ##' information in order to provide correct line numbers: ##' \itemize{ ##' \item On Linux/OS X use \code{compile(cppfile,"-O0 -g")}. ##' \item On Windows use \code{compile(cppfile,"-O1 -g",DLLFLAGS="")} (lower ##' optimization level will cause errors). ##' } ##' @title Source R-script through gdb to get backtrace. ##' @param file Your R script ##' @param interactive Run interactive gdb session? ##' @return Object of class \code{backtrace} gdbsource <- function(file,interactive=FALSE){ if(!file.exists(file))stop("File '",file,"' not found") if(.Platform$OS.type=="windows"){ return(.gdbsource.win(file,interactive)) } gdbscript <- tempfile() Rbin <- file.path(R.home('bin'), "R") if(interactive){ gdbcmd <- c(paste("run --vanilla <",file), "bt") gdbcmd <- paste(gdbcmd,"\n",collapse="") cat(gdbcmd,file=gdbscript) cmd <- paste(Rbin, "-d gdb --debugger-args=\"-x",gdbscript,"\"") system(cmd,intern=FALSE,ignore.stdout=FALSE,ignore.stderr=TRUE) return(NULL) } else { cat("run\nbt\nquit\n",file=gdbscript) cmd <- paste(Rbin, "--vanilla < ",file," -d gdb --debugger-args=\"-x", gdbscript,"\"") txt <- system(cmd,intern=TRUE,ignore.stdout=FALSE,ignore.stderr=TRUE) attr(txt,"file") <- file class(txt) <- "backtrace" return(txt) } } ## Windows case .gdbsource.win <- function(file,interactive=FALSE){ gdbscript <- tempfile() txt <- paste("set breakpoint pending on\nb abort\nrun --vanilla -f", file, "\nbt\n") cat(txt, file=gdbscript) cmd <- paste("gdb Rterm -x", gdbscript) if(interactive){ cmd <- paste("start",cmd) shell(cmd) return(NULL) } else { txt <- system(cmd,intern=TRUE,ignore.stdout=FALSE,ignore.stderr=TRUE) attr(txt,"file") <- file class(txt) <- "backtrace" return(txt) } } ##' If \code{gdbsource} is run non-interactively (the default) only ##' the relevant information will be printed. ##' ##' @title Print problematic cpp line number. ##' @param x Backtrace from \code{gdbsource} ##' @param ... Not used ##' @rdname gdbsource ##' @method print backtrace ##' @S3method print backtrace ##' @return NULL print.backtrace <- function(x,...){ ## Both gdb and lldb use the output format ## ' at file.cpp:123' ## to specify the problematic source lines: pattern <- "\\ at\\ .*\\.cpp\\:[0-9]+" x <- grep(pattern, x, value=TRUE) if (length(x) == 0) x <- "Program returned without errors" else x <- c("Errors:", x) cat(paste(x,"\n")) } TMB/R/dotCall.R0000644000176200001440000000732014243720065012607 0ustar liggesusers## ----------------------------------------------------------------------------- ## Fixed R-API to .Call within MakeADFun ## ----------------------------------------------------------------------------- ## General notes: ## - Some TMB functionality (DATA_UPDATE) implicitly assumes that 'env' ## can be found as the enclosing environment (parent.env) of ## 'reportenv' (!). It follows that reportenv must always be passed ## by the caller. getParameterOrder <- function(data, parameters, reportenv, DLL) { control <- NULL .Call("getParameterOrder", data, parameters, reportenv, control, PACKAGE=DLL) } ## ----------------------------------------------------------------------------- ## Constructors: MakeDoubleFunObject <- function(data, parameters, reportenv, DLL) { control <- NULL ans <- .Call("MakeDoubleFunObject", data, parameters, reportenv, control, PACKAGE=DLL) ans <- registerFinalizer(ans, DLL) ans } MakeADFunObject <- function(data, parameters, reportenv, ADreport=FALSE, DLL) { control <- list( report = as.integer(ADreport) ) ans <- .Call("MakeADFunObject", data, parameters, reportenv, control, PACKAGE=DLL) ans <- registerFinalizer(ans, DLL) ans } MakeADGradObject <- function(data, parameters, reportenv, random=NULL, f=NULL, DLL) { control <- list( f=f ) if (!is.null(random)) control$random <- as.integer(random) ans <- .Call("MakeADGradObject", data, parameters, reportenv, control, PACKAGE=DLL) ans <- registerFinalizer(ans, DLL) ans } ## gf (optional) = already calculated gradient object. ## skip (optional) = index vector of parameters to skip. MakeADHessObject <- function(data, parameters, reportenv, gf=NULL, skip=integer(0), DLL) { control <- list(gf=gf, skip=as.integer(skip)) ans <- .Call("MakeADHessObject2", data, parameters, reportenv, control, PACKAGE=DLL) ans <- registerFinalizer(ans, DLL) ans } ## ----------------------------------------------------------------------------- ## Evaluators EvalDoubleFunObject <- function(Fun, theta, do_simulate=FALSE, get_reportdims=FALSE) { theta <- as.double(theta) control = list(do_simulate = as.integer(do_simulate), get_reportdims = as.integer(get_reportdims) ) .Call("EvalDoubleFunObject", Fun$ptr, theta, control, PACKAGE=Fun$DLL) } EvalADFunObject <- function(ADFun, theta, order=0, hessiancols=NULL, hessianrows=NULL, sparsitypattern=FALSE, rangecomponent=1, rangeweight=NULL, dumpstack=FALSE, doforward=TRUE, set_tail=FALSE, keepx=NULL, keepy=NULL, data_changed=FALSE) { if (!is.null(rangeweight)) rangeweight <- as.double(rangeweight) control <- list(order=as.integer(order), hessiancols=as.integer(hessiancols), hessianrows=as.integer(hessianrows), sparsitypattern=as.integer(sparsitypattern), rangecomponent=as.integer(rangecomponent), rangeweight=rangeweight, dumpstack=as.integer(dumpstack), doforward=as.integer(doforward), set_tail = as.integer(set_tail), keepx=as.integer(keepx), keepy=as.integer(keepy), data_changed = as.integer(data_changed) ) .Call("EvalADFunObject", ADFun$ptr, theta, control, PACKAGE=ADFun$DLL) } TMB/R/graph_transform.R0000644000176200001440000000655414225262337014434 0ustar liggesusersTransformADFunObject <- function(ADFun, method, ... ) { .Call("TransformADFunObject", f = ADFun$ptr, control = list(method = as.character(method), ...), PACKAGE = ADFun$DLL) } ## Utility tape_print <- function(x, depth=0, method="tape", DLL=getUserDLL(), ...) { if (is.list(x)) x <- x$ptr control <- list(depth=as.integer(depth), method=as.character(method), ...) .Call("tmbad_print", x, control, PACKAGE=DLL) } op_table <- function(ADFun, name=TRUE, address=FALSE, input_size=FALSE, output_size=FALSE) { ntapes <- tape_print(ADFun, method="num_tapes", DLL=ADFun$DLL, i=as.integer(0)) ntapes <- max(1, ntapes) f <- function(i)tape_print(ADFun$ptr, method="op", DLL=ADFun$DLL, i=as.integer(i), name=as.integer(name), address=as.integer(address), input_size=as.integer(input_size), output_size=as.integer(output_size)) g <- function(i)data.frame(tape=i, opname=f(i), stringsAsFactors=FALSE) df <- do.call("rbind", lapply(seq_len(ntapes) - 1L, g)) table(opname = df$opname, tape = df$tape) } src_transform <- function(ADFun, flags = "-O3", ..., perm=TRUE) { if(.Platform$OS.type=="windows"){ ## Overload tempfile tempfile <- function(...){ ans <- base::tempfile(...) chartr("\\", "/", shortPathName(ans)) } } ntapes <- tape_print(ADFun, method="num_tapes", DLL=ADFun$DLL, i=as.integer(0)) ntapes <- max(1, ntapes) tapes <- seq.int(from=0, length.out=ntapes) control <- list(method="src") dll <- tempfile(fileext=paste0("_",tapes)) dll.cpp <- paste0(dll, ".cpp") ## Reorder graph if (perm) { TransformADFunObject( ADFun, method="reorder_sub_expressions", random_order=integer(0), max_period_size=1024L) } ## Write redefs forward <- paste0("forward", tapes) reverse <- paste0("reverse", tapes) redef <- function(i) { cat("#define forward", forward[i+1], "\n") cat("#define reverse", reverse[i+1], "\n") } ## Write source code for (i in tapes) { control$i <- i sink(dll.cpp[i+1]); redef(i); out <- .Call("tmbad_print", ADFun$ptr, control, PACKAGE = ADFun$DLL); sink(NULL) } ## Overload compile(dll.cpp, flags=flags, ..., libtmb=FALSE) dyn.load(dynlib(dll)[1]) dllinfo <- getLoadedDLLs()[[basename(dll[1])]] forward_compiled <- lapply(forward, function(x)getNativeSymbolInfo(x,PACKAGE=dllinfo)$address) reverse_compiled <- lapply(reverse, function(x)getNativeSymbolInfo(x,PACKAGE=dllinfo)$address) TransformADFunObject( ADFun, method="set_compiled", forward_compiled=forward_compiled, reverse_compiled=reverse_compiled) ## Unload compiled code when no longer needed finalizer <- function(ptr) { dyn.unload(dynlib(dll[1])) file.remove(dynlib(dll[1])) file.remove(paste0(dll, ".o")) file.remove(dll.cpp) } reg.finalizer(ADFun$ptr, finalizer) NULL } TMB/R/tmbroot.R0000644000176200001440000001247514113627760012726 0ustar liggesusers##' Compute likelihood profile confidence intervals of a TMB object by root-finding ##' in contrast to \code{\link{tmbprofile}}, which tries to compute ##' somewhat equally spaced values along the likelihood profile (which ##' is useful for visualizing the shape of the likelihood surface), ##' and then (via \code{\link{confint.tmbprofile}}) extracting a ##' critical value by linear interpolation, ##' ##' @title Compute likelihood profile confidence intervals of a TMB object by root-finding ##' @inheritParams tmbprofile ##' @param target desired deviation from minimum log-likelihood. Default ##' is set to retrieve the 95% likelihood profile confidence interval, ##' if the objective function is a negative log-likelihood function ##' @param parm.range lower and upper limits; if \code{NA}, ##' a value will be guessed based on the parameter value and \code{sd.range} ##' @param sd.range in the absence of explicit \code{parm.range} values, ##' the range chosen will be the parameter value plus or minus \code{sd.range} ##' times the corresponding standard deviation. ##' May be specified as a two-element vector for different ranges below and ##' above the parameter value. ##' @param trace report information? ##' @param continuation use continuation method, i.e. set starting parameters for non-focal parameters to solutions from previous fits? ##' @return a two-element numeric vector containing the lower and upper limits (or \code{NA} if the target is not achieved in the range), with an attribute giving the total number of function iterations used ##' @examples ##' \dontrun{ ##' runExample("simple",thisR=TRUE) ##' logsd0.ci <- tmbroot(obj,"logsd0") ##' } tmbroot <- function (obj, name, target=0.5*qchisq(0.95,df=1), lincomb, parm.range = c(NA,NA), sd.range = 7, trace = FALSE, continuation = FALSE) { ## continuation method works well for profiling, where ## each fit starts "close" to previous values, but may be ## counterproductive for root-finding, when we are jumping back ## and forth ... restore.on.exit <- c("last.par.best", "random.start", "value.best", "last.par", "inner.control", "tracemgc") oldvars <- sapply(restore.on.exit, get, envir = obj$env, simplify = FALSE) restore.oldvars <- function() { for (var in names(oldvars)) assign(var, oldvars[[var]], envir = obj$env) } on.exit(restore.oldvars()) par <- obj$env$last.par.best if (!is.null(obj$env$random)) par <- par[-obj$env$random] if (missing(lincomb)) { if (missing(name)) stop("No 'name' or 'lincomb' specified") stopifnot(length(name) == 1) if (is.numeric(name)) { lincomb <- as.numeric(1:length(par) == name) name <- names(par)[name] } else if (is.character(name)) { if (sum(names(par) == name) != 1) stop("'name' is not unique") lincomb <- as.numeric(names(par) == name) } else stop("Invalid name argument") } else { if (missing(name)) name <- "parameter" } stopifnot(length(lincomb) == length(par)) X <- Diagonal(length(lincomb)) i <- which(lincomb != 0)[1] X[i, ] <- lincomb invX <- solve(X) direction <- invX[, i] C <- invX[, -i, drop = FALSE] that <- sum(lincomb * par) f <- function(x) { par <- par + x * direction if (length(C)==0) { return(obj$fn(par)) } newfn <- function(par0) { par <- par + as.vector(C %*% par0) obj$fn(par) } newgr <- function(par0) { par <- par + as.vector(C %*% par0) as.vector(obj$gr(par) %*% C) } obj$env$value.best <- Inf obj$env$inner.control$trace <- FALSE obj$env$tracemgc <- FALSE control <- list(step.min = 0.001) ans <- nlminb(start, newfn, newgr, control = control) if (continuation) start <<- ans$par conv <<- ans$convergence if (trace) cat("Profile value:", ans$objective, "\n") ans$objective } f.original <- f f <- function(x) { y <- try(f.original(x), silent = TRUE) if (is(y, "try-error")) y <- NA y } g <- function(x) { return(f(x)-v.0-target) } if (any(is.na(parm.range))) { sds <- sdreport(obj) sd0 <- drop(sqrt(lincomb %*% sds$cov.fixed %*% matrix(lincomb))) if (length(sd.range)==1) sd.range <- rep(sd.range,2) parm.range[is.na(parm.range)] <- c(-1,1)*sd0*sd.range[is.na(parm.range)] } ## need to set start in order for f() to work ... ## FIXME: check convergence code ... conv <- 0 start <- rep(0, length(par) - 1) v.0 <- f(0) ## need to set v.0 for g() ... lwr.x <- g(parm.range[1]) if (is.na(lwr.x) || lwr.x<0) { lwr <- list(root=NA,iter=0) } else { lwr <- uniroot(g,interval=c(parm.range[1],0)) } ## reset for upper root-finding restore.oldvars() start <- rep(0, length(par) - 1) upr.x <- g(parm.range[2]) if (is.na(upr.x) || upr.x<0) { upr <- list(root=NA,iter=0) } else { upr <- uniroot(g,interval=c(0,parm.range[2])) } ans <- c(lwr=that+lwr$root,upr=that+upr$root) attr(ans,"iter") <- lwr$iter+upr$iter return(ans) } TMB/R/utils.R0000644000176200001440000000160014225262337012363 0ustar liggesusers## Get *subset* of inverse of sparse matrix Q. ## Subset is guarantied to contain pattern of Q. ## Q: Sparse positive definite matrix. ## L: Cholesky factor of Q. ## diag: Return just diagonal of inverse ? solveSubset <- function(Q, L = Matrix::Cholesky(Q, super=TRUE, perm=TRUE), diag = FALSE) { stopifnot( is(L, "dCHMsuper") ) invQ <- .Call("tmb_invQ", L, PACKAGE = "TMB") iperm <- Matrix::invPerm(L@perm + 1L) if (diag) { invQ <- diag(invQ)[iperm] } else { invQ <- invQ[iperm, iperm, drop=FALSE] } invQ } ## Get information on ADFun object pointer info <- function(ADFun, DLL = getUserDLL()) { ptr <- ADFun$ptr DLL <- ADFun$DLL ok <- is(ptr, "externalptr") && !isNullPointer(ptr) if (!ok) stop("'ptr' is not a valid external pointer") .Call("InfoADFunObject", ptr, PACKAGE=DLL) } TMB/R/zzz.R0000644000176200001440000000422414536067012012063 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ## .First.lib <- function(lib, pkg) { ## library.dynam("TMB", pkg, lib) ## } ## Matrix package versions that are likely to break ABI compatibility: MVI <- c("1.6-2", "1.7-0") ## findInterval findMVI <- function(v) { sum(MVI <= numeric_version(v)) } sameMVI <- function(x, y) { findMVI(x) == findMVI(y) } checkMatrixPackageVersion <- function(warn=TRUE) { ## It is unsafe to use the TMB package with versions of 'Matrix' ## other than the one TMB was originally built with. file <- paste0(system.file(package="TMB"),"/Matrix-version") cur.Matrix.version <- as.character(packageVersion("Matrix")) if(!file.exists(file)) { writeLines(cur.Matrix.version, con = file) } TMB.Matrix.version <- readLines(file) if(warn && !sameMVI(TMB.Matrix.version, cur.Matrix.version)) { warning( "Package version inconsistency detected.\n", "TMB was built with Matrix version ", TMB.Matrix.version, "\n", "Current Matrix version is ", cur.Matrix.version, "\n", "Please re-install 'TMB' from source using install.packages('TMB', type = 'source') ", "or ask CRAN for a binary version of 'TMB' matching CRAN's 'Matrix' package" ) } } .onLoad <- function(lib, pkg) { library.dynam("TMB", pkg, lib) checkMatrixPackageVersion(getOption("TMB.check.Matrix", TRUE)) ## Select AD framework (CppAD or TMBad) used by TMB::compile tmb.ad.framework <- getOption("tmb.ad.framework", NULL) if (is.null(tmb.ad.framework)) tmb.ad.framework <- Sys.getenv("TMB_AD_FRAMEWORK", "CppAD") options("tmb.ad.framework" = tmb.ad.framework) } .onUnload <- function(libpath) { library.dynam.unload("TMB", libpath) } ## .LastLib <- function(libpath) ## { ## library.dynam.unload("TMB", libpath) ## } .onAttach <- function(lib, pkg) { exfolder <- system.file("examples", package = "TMB") dll <- paste0(exfolder, Sys.getenv("R_ARCH"), "/simple", .Platform$dynlib.ext) if(!file.exists(dll)) runExample("simple", dontrun=TRUE, eigen.disable.warnings=FALSE) } TMB/R/config.R0000644000176200001440000000271014243720065012470 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ##' Get or set internal configuration variables of user's DLL. ##' ##' A model compiled with the \code{TMB} C++ library has several ##' configuration variables set by default. The variables can be read ##' and modified using this function. The meaning of the variables can ##' be found in the Doxygen documentation. ##' ##' @title Get or set internal configuration variables ##' @param ... Variables to set ##' @param DLL Name of user's DLL. Auto-detected if missing. ##' @return List with current configuration ##' @examples ##' \dontrun{ ##' ## Load library ##' dyn.load(dynlib("mymodel")) ##' ## Read the current settings ##' config(DLL="mymodel") ##' ## Reduce memory peak of a parallel model by creating tapes in serial ##' config(tape.parallel=0, DLL="mymodel") ##' obj <- MakeADFun(..., DLL="mymodel") ##' } config <- function(...,DLL=getUserDLL()){ new <- list(...) ## Get e <- new.env() .Call("TMBconfig",e,as.integer(1),PACKAGE=DLL) conf <- eapply(e,as.integer) ## Set conf[names(new)] <- new conf <- lapply(conf,as.integer) e <- local(environment(),conf) .Call("TMBconfig",e,as.integer(2),PACKAGE=DLL) ## Get e <- new.env() .Call("TMBconfig",e,as.integer(1),PACKAGE=DLL) conf <- eapply(e,as.integer) ## Backwards compatibility (don't break if members unavailable) if (is.null(conf$autopar)) conf$autopar <- FALSE if (is.null(conf$nthreads)) conf$nthreads <- 1 conf } TMB/R/benchmark.R0000644000176200001440000000676714225262337013200 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ##' Benchmark parallel templates ##' ##' By default this function will perform timings of the most critical ##' parts of an AD model, specifically ##' \enumerate{ ##' \item Objective function of evaluated template. ##' \item Gradient of evaluated template. ##' \item Sparse hessian of evaluated template. ##' \item Cholesky factorization of sparse hessian. ##' } ##' (for pure fixed effect models only the first two). ##' Expressions to time can be overwritten by the user (\code{expr}). ##' A \code{plot} method is available for Parallel benchmarks. ##' ##' @title Benchmark parallel templates ##' @param obj Object from \code{MakeADFun} ##' @param n Number of replicates to obtain reliable results. ##' @param expr Optional expression to benchmark instead of default. ##' @param cores Optional vector of cores. ##' @examples ##' \dontrun{ ##' runExample("linreg_parallel",thisR=TRUE) ## Create obj ##' ben <- benchmark(obj,n=100,cores=1:4) ##' plot(ben) ##' ben <- benchmark(obj,n=10,cores=1:4,expr=expression(do.call("optim",obj))) ##' plot(ben) ##' } benchmark <- function(obj,n=10,expr=NULL,cores=NULL){ if(!is.null(cores)){ return(parallelBenchmark(obj,n=n,cores=cores,expr=expr)) } if(is.null(expr)){ ## Expressions to time expr <- expression( template.likelihood = obj$env$f(order=0), template.gradient = obj$env$f(order=1), template.sparse.hessian = obj$env$spHess(random=TRUE), cholesky=updateCholesky(L,h) ) } else if(is.null(names(expr))) names(expr) <- vapply(expr, function(.) deparse(.)[[1L]], "") addLoopToExpression <- function(y) substitute(for (i in seq_len(n)) { obj$env$.data <- NULL; EE }, list(EE=y)) expr <- lapply(expr, addLoopToExpression) if(!is.null(obj$env$random)){ h <- obj$env$spHess() ## Avoid timing the construction h@x[] <- 0 diag(h) <- 1 L <- Cholesky(h,super=TRUE) } else { expr$template.sparse.hessian <- NULL expr$cholesky <- NULL } ans <- lapply(expr,function(x)system.time(eval(x))) ans <- do.call("rbind",ans) as.data.frame(ans)[c(3)] } ## Internal helper function parallelBenchmark <- function(obj,n,cores=1:4,...){ ans <- lapply(cores,function(nc){ openmp(nc) obj$env$retape() benchmark(obj,n=n,cores=NULL,...) }) ans <- t(do.call("cbind",ans)) rownames(ans) <- cores names(dimnames(ans)) <- c("ncores","") ans <- t(ans) class(ans) <- "parallelBenchmark" ans } ##' Plot result of parallel benchmark ##' ##' @title Plot result of benchmark ##' @param x Object to plot ##' @param type Plot type ##' @param ... Further plot arguments ##' @param show Plot relative speedup or relative time? ##' @param legendpos Position of legend ##' @return NULL ##' @rdname benchmark ##' @method plot parallelBenchmark ##' @S3method plot parallelBenchmark plot.parallelBenchmark <- function(x,type="b",...,show=c("speedup","time"),legendpos="topleft"){ show <- match.arg(show) ncores <- as.numeric(colnames(x)) x <- x[,order(ncores),drop=FALSE] ncores <- sort(ncores) if(show=="time"){ matplot(ncores,t(x/x[,1]),ylab="Time (relative to one core)",type=type,...) plot(function(x)1/x,min(ncores),max(ncores),add=TRUE,col="grey") } if(show=="speedup"){ matplot(ncores,t(x[,1]/x),type=type,ylab="Speedup (relative to one core)",...) abline(0,1,col="grey") } if(!is.null(legendpos)){ n <- nrow(x) if(is.null(rownames(x)))rownames(x) <- 1:n legend(legendpos,legend=rownames(x),col=1:n,lty=1:n) } NULL } TMB/R/normalize.R0000644000176200001440000000716314113627760013236 0ustar liggesusers##' Normalize process likelihood using the Laplace approximation. ##' ##' If the random effect likelihood contribution of a model has been ##' implemented without proper normalization (i.e. lacks the normalizing ##' constant), then this function can perform the adjustment ##' automatically. In order for this to work, the model must include a ##' flag that disables the data term so that the un-normalized random effect ##' (negative log) density is returned from the model template. ##' Automatic process normalization may be useful if either the ##' normalizing constant is difficult to implement, or if its calulation ##' involves so many operations that it becomes infeasible to include in ##' the AD machinery. ##' ##' @param obj Model object from \code{MakeADFun} without proper normalization of the random effect likelihood. ##' @param flag Flag to disable the data term from the model. ##' @param value Value of 'flag' that signifies to not include the data term. ##' @return Modified model object that can be passed to an optimizer. normalize <- function(obj, flag, value=0) { obj1 <- obj ## Data included tracemgc <- obj1$env$tracemgc obj1$env$tracemgc <- FALSE ## Deep copy obj0 <- unserialize(serialize(obj, NULL)) obj0$env$L.created.by.newton <- NULL ## Can't use same Cholesky object if (missing(flag) || ! is.character(flag) || ! all( flag %in% names(obj0$env$data) ) ) { stop("'flag' must be a character vector naming one or more data items.") } if ( (length(flag)==1) && length(value) > 0) { ## Examples: flag="flag" and value=0 ("flag" ~ INTEGER) ## flag="keep" and value=0 ("keep" ~ DATA_VECTOR_INDICATOR) obj0$env$data[[flag]][] <- value } else { ## Examples: flag="obs" and value=numeric(0) ("obs" ~ DATA_VECTOR) ## flag=c("obs1","obs2") and value=list(numeric(0),numeric(0)) if (!is.list(value)) value <- list(value) obj0$env$data[flag] <- value } obj0$retape() newobj <- list() newobj$par <- obj1$par newobj$env <- obj1$env ## Workaround: Insert NAs in invalid hessian block H[fixed, fixed] ## if accessed by e.g. 'sdreport': random <- NULL ## CRAN check: no visible binding local({ f_old <- f f <- function(...) { args <- list(...) ans <- f_old(...) if ((args$order == 1) && (args$type == "ADGrad") && is.vector(args$rangeweight) ) { if ( ! all( args$rangeweight[-random] == 0 ) ) { ans[-random] <- NA } } ans } }, newobj$env) newobj$fn <- function(x = newobj$par) { env <- newobj$env value.best <- env$value.best last.par.best <- env$last.par.best ans <- obj1$fn(x) - obj0$fn(x) last.par <- env$last.par if (is.finite(ans)) { if (ans < value.best) { env$last.par.best <- last.par env$value.best <- ans } } ans } newobj$gr <- function(x = newobj$par) { ans <- obj1$gr(x) - obj0$gr(x) if (tracemgc) cat("outer mgc: ", max(abs(ans)), "\n") ans } newobj$he <- function(x = newobj$par) { ans <- obj1$he(x) - obj0$he(x) ans } newobj$report <- obj1$env$report newobj$simulate <- obj1$env$simulate newobj$retape <- function(...) { obj1$retape(...); obj0$retape(...) } ## Ensure all slots are present: nm.diff <- setdiff(names(obj1), names(newobj)) newobj[nm.diff] <- obj1[nm.diff] newobj } TMB/R/sdreport.R0000644000176200001440000005702414276702134013100 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ##' After optimization of an AD model, \code{sdreport} is used to ##' calculate standard deviations of all model parameters, including ##' non linear functions of random effects and parameters specified ##' through the ADREPORT() macro from the user template. ##' ##' First, the Hessian wrt. the parameter vector (\eqn{\theta}) is ##' calculated. The parameter covariance matrix is approximated by ##' \deqn{V(\hat\theta)=-\nabla^2 l(\hat\theta)^{-1}} where \eqn{l} ##' denotes the log likelihood function (i.e. \code{-obj$fn}). If ##' \code{ignore.parm.uncertainty=TRUE} then the Hessian calculation ##' is omitted and a zero-matrix is used in place of ##' \eqn{V(\hat\theta)}. ##' ##' For non-random effect models the standard delta-method is used to ##' calculate the covariance matrix of transformed parameters. Let ##' \eqn{\phi(\theta)} denote some non-linear function of ##' \eqn{\theta}. Then \deqn{V(\phi(\hat\theta))\approx \nabla\phi ##' V(\hat\theta) \nabla\phi'} ##' ##' The covariance matrix of reported variables ##' \eqn{V(\phi(\hat\theta))} is returned by default. This can cause ##' high memory usage if many variables are ADREPORTed. Use ##' \code{getReportCovariance=FALSE} to only return standard errors. ##' In case standard deviations are not required one can completely skip ##' the delta method using \code{skip.delta.method=TRUE}. ##' ##' For random effect models a generalized delta-method is used. First ##' the joint covariance of random effect and parameter estimation error is approximated ##' by ##' \deqn{V \left( \begin{array}{cc} \hat u - u \cr \hat\theta - \theta \end{array} \right) \approx ##' \left( \begin{array}{cc} H_{uu}^{-1} & 0 \cr 0 & 0 \end{array} \right) + ##' J V(\hat\theta) J' ##' } ##' where \eqn{H_{uu}} denotes random effect block of the full joint ##' Hessian of \code{obj$env$f} and \eqn{J} denotes the Jacobian of ##' \eqn{\left( \begin{array}{cc}\hat u(\theta) \cr \theta \end{array} \right)} wrt. \eqn{\theta}. ##' Here, the first term represents the expected conditional variance ##' of the estimation error given the data and the second term represents the variance ##' of the conditional mean of the estimation error given the data. ##' ##' Now the delta method can be applied on a general non-linear ##' function \eqn{\phi(u,\theta)} of random effects \eqn{u} and ##' parameters \eqn{\theta}: ##' \deqn{V\left(\phi(\hat u,\hat\theta) - \phi(u,\theta) \right)\approx \nabla\phi V \left( \begin{array}{cc} ##' \hat u - u \cr \hat\theta - \theta \end{array} \right) \nabla\phi'} ##' ##' The full joint covariance is not returned by default, because it ##' may require large amounts of memory. It may be obtained by ##' specifying \code{getJointPrecision=TRUE}, in which case \eqn{V ##' \left( \begin{array}{cc} \hat u - u \cr \hat\theta - \theta \end{array} \right) ^{-1} } will be part of the ##' output. This matrix must be manually inverted using ##' \code{solve(jointPrecision)} in order to get the joint covariance ##' matrix. Note, that the parameter order will follow the original ##' order (i.e. \code{obj$env$par}). ##' ##' Using \eqn{\phi(\hat u,\theta)} as estimator of ##' \eqn{\phi(u,\theta)} may result in substantial bias. This may be ##' the case if either \eqn{\phi} is non-linear or if the distribution ##' of \eqn{u} given \eqn{x} (data) is sufficiently non-symmetric. A ##' generic correction is enabled with \code{bias.correct=TRUE}. It is ##' based on the identity ##' \deqn{E_{\theta}[\phi(u,\theta)|x] = ##' \partial_\varepsilon\left(\log \int \exp(-f(u,\theta) + ##' \varepsilon \phi(u,\theta))\:du\right)_{|\varepsilon=0}} ##' stating that the conditional expectation can be written as a ##' marginal likelihood gradient wrt. a nuisance parameter ##' \eqn{\varepsilon}. ##' The marginal likelihood is replaced by its Laplace approximation. ##' ##' If \code{bias.correct.control$sd=TRUE} the variance of the ##' estimator is calculated using ##' \deqn{V_{\theta}[\phi(u,\theta)|x] = ##' \partial_\varepsilon^2\left(\log \int \exp(-f(u,\theta) + ##' \varepsilon \phi(u,\theta))\:du\right)_{|\varepsilon=0}} ##' A further correction is added to this variance to account for the ##' effect of replacing \eqn{\theta} by the MLE \eqn{\hat\theta} ##' (unless \code{ignore.parm.uncertainty=TRUE}). ##' ##' Bias correction can be be performed in chunks in order to reduce ##' memory usage or in order to only bias correct a subset of ##' variables. First option is to pass a list of indices as ##' \code{bias.correct.control$split}. E.g. a list ##' \code{list(1:2,3:4)} calculates the first four ADREPORTed ##' variables in two chunks. ##' The internal function \code{obj$env$ADreportIndex()} ##' gives an overview of the possible indices of ADREPORTed variables. ##' ##' Second option is to pass the number of ##' chunks as \code{bias.correct.control$nsplit} in which case all ##' ADREPORTed variables are bias corrected in the specified number of ##' chunks. ##' Also note that \code{skip.delta.method} may be necessary when bias ##' correcting a large number of variables. ##' ##' @title General sdreport function. ##' @param obj Object returned by \code{MakeADFun} ##' @param par.fixed Optional. Parameter estimate (will be known to \code{obj} when an optimization has been carried out). ##' @param hessian.fixed Optional. Hessian wrt. parameters (will be calculated from \code{obj} if missing). ##' @param getJointPrecision Optional. Return full joint precision matrix of random effects and parameters? ##' @param bias.correct logical indicating if bias correction should be applied ##' @param bias.correct.control a \code{list} of bias correction options; currently \code{sd}, \code{split} and \code{nsplit} are used - see details. ##' @param ignore.parm.uncertainty Optional. Ignore estimation variance of parameters? ##' @param getReportCovariance Get full covariance matrix of ADREPORTed variables? ##' @param skip.delta.method Skip the delta method? (\code{FALSE} by default) ##' @return Object of class \code{sdreport} ##' @seealso \code{\link{summary.sdreport}}, \code{\link{print.sdreport}}, \code{\link{as.list.sdreport}} ##' @examples ##' \dontrun{ ##' runExample("linreg_parallel", thisR = TRUE) ## Non-random effect example ##' sdreport(obj) } ##' ##' runExample("simple", thisR = TRUE) ## Random effect example ##' rep <- sdreport(obj) ##' summary(rep, "random") ## Only random effects ##' summary(rep, "fixed", p.value = TRUE) ## Only non-random effects ##' summary(rep, "report") ## Only report ##' ##' ## Bias correction ##' rep <- sdreport(obj, bias.correct = TRUE) ##' summary(rep, "report") ## Include bias correction sdreport <- function(obj,par.fixed=NULL,hessian.fixed=NULL,getJointPrecision=FALSE,bias.correct=FALSE, bias.correct.control=list(sd=FALSE, split=NULL, nsplit=NULL), ignore.parm.uncertainty = FALSE, getReportCovariance=TRUE, skip.delta.method=FALSE){ if(is.null(obj$env$ADGrad) & (!is.null(obj$env$random))) stop("Cannot calculate sd's without type ADGrad available in object for random effect models.") ## Make object to calculate ADREPORT vector obj2 <- MakeADFun(obj$env$data, obj$env$parameters, type = "ADFun", ADreport = TRUE, DLL = obj$env$DLL, silent = obj$env$silent) r <- obj$env$random ## Get full parameter (par), Fixed effects parameter (par.fixed) ## and fixed effect gradient (gradient.fixed) if(is.null(par.fixed)){ ## Parameter estimate not specified - use best encountered parameter par <- obj$env$last.par.best if(!is.null(r))par.fixed <- par[-r] else par.fixed <- par gradient.fixed <- obj$gr(par.fixed) } else { gradient.fixed <- obj$gr(par.fixed) ## <-- updates last.par par <- obj$env$last.par } ## In case of empty parameter vector: if(length(par.fixed)==0) ignore.parm.uncertainty <- TRUE ## Get Hessian wrt. fixed effects (hessian.fixed) and check if positive definite (pdHess). if(ignore.parm.uncertainty){ hessian.fixed <- NULL pdHess <- TRUE Vtheta <- matrix(0, length(par.fixed), length(par.fixed)) } else { if(is.null(hessian.fixed)){ hessian.fixed <- optimHess(par.fixed,obj$fn,obj$gr) ## Marginal precision of theta. } pdHess <- !is.character(try(chol(hessian.fixed),silent=TRUE)) Vtheta <- try(solve(hessian.fixed),silent=TRUE) if(is(Vtheta, "try-error")) Vtheta <- hessian.fixed * NaN } ## Get random effect block of the full joint Hessian (hessian.random) and its ## Cholesky factor (L) if(!is.null(r)){ hessian.random <- obj$env$spHess(par,random=TRUE) ## Conditional prec. of u|theta L <- obj$env$L.created.by.newton if(!is.null(L)){ ## Re-use symbolic factorization if exists updateCholesky(L,hessian.random) hessian.random@factors <- list(SPdCholesky=L) } } ## Get ADreport vector (phi) phi <- try(obj2$fn(par), silent=TRUE) ## NOTE_1: obj2 forward sweep now initialized ! if(is.character(phi) | length(phi)==0){ phi <- numeric(0) } ADGradForward0Initialized <- FALSE ADGradForward0Initialize <- function() { ## NOTE_2: ADGrad forward sweep now initialized ! obj$env$f(par, order = 0, type = "ADGrad") ADGradForward0Initialized <<- TRUE } doDeltaMethod <- function(chunk=NULL){ ## ======== Determine case ## If no random effects use standard delta method simpleCase <- is.null(r) if(length(phi)==0){ ## Nothing to report simpleCase <- TRUE } else { ## Something to report - get derivatives if(is.null(chunk)){ ## Do all at once Dphi <- obj2$gr(par) } else { ## Do *chunk* only ## Reduce to Dphi[chunk,] and phi[chunk] w <- rep(0, length(phi)) phiDeriv <- function(i){ w[i] <- 1 obj2$env$f(par, order=1, rangeweight=w, doforward=0) ## See NOTE_1 } Dphi <- t( sapply(chunk, phiDeriv) ) phi <- phi[chunk] } if(!is.null(r)){ Dphi.random <- Dphi[,r,drop=FALSE] Dphi.fixed <- Dphi[,-r,drop=FALSE] if(all(Dphi.random==0)){ ## Fall back to simple case simpleCase <- TRUE Dphi <- Dphi.fixed } } } ## ======== Do delta method ## Get covariance (cov) if(simpleCase){ if(length(phi)>0){ cov <- Dphi %*% Vtheta %*% t(Dphi) } else cov <- matrix(,0,0) } else { tmp <- solve(hessian.random,t(Dphi.random)) tmp <- as.matrix(tmp) term1 <- Dphi.random%*%tmp ## first term. if(ignore.parm.uncertainty){ term2 <- 0 } else { ## Use columns of tmp as direction for reverse mode sweep f <- obj$env$f w <- rep(0, length(par)) if(!ADGradForward0Initialized) ADGradForward0Initialize() reverse.sweep <- function(i){ w[r] <- tmp[,i] -f(par, order = 1, type = "ADGrad", rangeweight = w, doforward=0)[-r] } A <- t(do.call("cbind",lapply(seq_along(phi), reverse.sweep))) + Dphi.fixed term2 <- A %*% (Vtheta %*% t(A)) ## second term } cov <- term1 + term2 } ##list(phi=phi, cov=cov) cov } if (!skip.delta.method) { if (getReportCovariance) { ## Get all cov <- doDeltaMethod() sd <- sqrt(diag(cov)) } else { tmp <- lapply(seq_along(phi), doDeltaMethod) sd <- sqrt(as.numeric(unlist(tmp))) cov <- NA } } else { sd <- rep(NA, length(phi)) cov <- NA } ## Output ans <- list(value=phi,sd=sd,cov=cov,par.fixed=par.fixed, cov.fixed=Vtheta,pdHess=pdHess, gradient.fixed=gradient.fixed) ## ======== Calculate bias corrected random effects estimates if requested if(bias.correct){ epsilon <- rep(0,length(phi)) names(epsilon) <- names(phi) parameters <- obj$env$parameters parameters$TMB_epsilon_ <- epsilon ## Appends to list without changing attributes doEpsilonMethod <- function(chunk = NULL) { if(!is.null(chunk)) { ## Only do *chunk* mapfac <- rep(NA, length(phi)) mapfac[chunk] <- chunk parameters$TMB_epsilon_ <- updateMap(parameters$TMB_epsilon_, factor(mapfac) ) } obj3 <- MakeADFun(obj$env$data, parameters, random = obj$env$random, checkParameterOrder = FALSE, DLL = obj$env$DLL, silent = obj$env$silent) ## Get good initial parameters obj3$env$start <- c(par, epsilon) obj3$env$random.start <- expression(start[random]) ## Test if Hessian pattern is un-changed h <- obj$env$spHess(random=TRUE) h3 <- obj3$env$spHess(random=TRUE) pattern.unchanged <- identical(h@i,h3@i) & identical(h@p,h3@p) ## If pattern un-changed we can re-use symbolic Cholesky: if(pattern.unchanged){ if(!obj$env$silent) cat("Re-using symbolic Cholesky\n") obj3$env$L.created.by.newton <- L } else { if( .Call("have_tmb_symbolic", PACKAGE = "TMB") ) runSymbolicAnalysis(obj3) } if(!is.null(chunk)) epsilon <- epsilon[chunk] par.full <- c(par.fixed, epsilon) i <- (1:length(par.full)) > length(par.fixed) ## epsilon indices grad <- obj3$gr(par.full) Vestimate <- if(bias.correct.control$sd) { ## requireNamespace("numDeriv") hess <- numDeriv::jacobian(obj3$gr, par.full) -hess[i,i] + hess[i,!i] %*% Vtheta %*% hess[!i,i] } else matrix(NA) estimate <- grad[i] names(estimate) <- names(epsilon) list(value=estimate, sd=sqrt(diag(Vestimate)), cov=Vestimate) } nsplit <- bias.correct.control$nsplit if(is.null(nsplit)) { split <- bias.correct.control$split } else { split <- split(seq_along(phi), cut(seq_along(phi), nsplit)) } if( is.null( split ) ){ ## Get all ans$unbiased <- doEpsilonMethod() } else { tmp <- lapply(split, doEpsilonMethod) m <- if (bias.correct.control$sd) length(phi) else 1 ans$unbiased <- list(value = rep(NA, length(phi)), sd = rep(NA, m), cov = matrix(NA, m, m)) for(i in seq_along(split)) { ans$unbiased$value[ split[[i]] ] <- tmp[[i]]$value if (bias.correct.control$sd) { ans$unbiased$sd [ split[[i]] ] <- tmp[[i]]$sd ans$unbiased$cov [ split[[i]], split[[i]] ] <- tmp[[i]]$cov } } } } ## ======== Find marginal variances of all random effects i.e. phi(u,theta)=u if(!is.null(r)){ if(is(L,"dCHMsuper")){ ## Required by inverse subset algorithm diag.term1 <- solveSubset(L=L, diag=TRUE) if(ignore.parm.uncertainty){ diag.term2 <- 0 } else { f <- obj$env$f w <- rep(0, length(par)) if(!ADGradForward0Initialized) ADGradForward0Initialize() reverse.sweep <- function(i){ w[i] <- 1 f(par, order = 1, type = "ADGrad", rangeweight = w, doforward=0)[r] } nonr <- setdiff(seq_along(par), r) framework <- .Call("getFramework", PACKAGE=obj$env$DLL) if (framework != "TMBad") tmp <- sapply(nonr,reverse.sweep) else tmp <- f(par, order = 1, type = "ADGrad", keepx=nonr, keepy=r) ## TMBad only !!! if(!is.matrix(tmp)) ## Happens if length(r)==1 tmp <- matrix(tmp, ncol=length(nonr) ) A <- solve(hessian.random, tmp) diag.term2 <- rowSums((A %*% Vtheta)*A) } ans$par.random <- par[r] ans$diag.cov.random <- diag.term1 + diag.term2 if(getJointPrecision){ ## Get V(u,theta)^-1 if(length(par.fixed) == 0) { ans$jointPrecision <- hessian.random } else if (!ignore.parm.uncertainty) { G <- hessian.random %*% A G <- as.matrix(G) ## Avoid Matrix::cbind2('dsCMatrix','dgeMatrix') M1 <- cbind2(hessian.random,G) M2 <- cbind2(t(G), as.matrix(t(A)%*%G)+hessian.fixed ) M <- rbind2(M1,M2) M <- forceSymmetric(M,uplo="L") dn <- c(names(par)[r],names(par[-r])) dimnames(M) <- list(dn,dn) p <- invPerm(c(r,(1:length(par))[-r])) ans$jointPrecision <- M[p,p] } else { warning("ignore.parm.uncertainty ==> No joint precision available") } } } else { warning("Could not report sd's of full randomeffect vector.") } } ## Copy a few selected members of the environment 'env'. In ## particular we need the 'skeleton' objects that allow us to put ## results back in same shape as original parameter list. ans$env <- new.env(parent = emptyenv()) ans$env$parameters <- obj$env$parameters ans$env$random <- obj$env$random ans$env$ADreportDims <- obj2$env$ADreportDims class(ans) <- "sdreport" ans } ##' Extract parameters, random effects and reported variables along ##' with uncertainties and optionally Chi-square statistics. Bias ##' corrected quantities are added as additional columns if available. ##' ##' @title summary tables of model parameters ##' @param object Output from \code{\link{sdreport}} ##' @param select Parameter classes to select. Can be any subset of ##' \code{"fixed"} (\eqn{\hat\theta}), \code{"random"} (\eqn{\hat u}) or ##' \code{"report"} (\eqn{\phi(\hat u,\hat\theta)}) using notation as ##' \code{\link{sdreport}}. ##' @param p.value Add column with approximate p-values ##' @param ... Not used ##' @return matrix ##' @method summary sdreport ##' @S3method summary sdreport summary.sdreport <- function(object, select = c("all", "fixed", "random", "report"), p.value=FALSE, ...) { select <- match.arg(select, several.ok = TRUE)# *several* : e.g. c("fixed", "report") ## check if 'meth' (or "all") is among the 'select'ed ones : s.has <- function(meth) any(match(c(meth, "all"), select, nomatch=0L)) > 0L ans1 <- ans2 <- ans3 <- NULL if(s.has("fixed")) ans1 <- cbind(object$par.fixed, sqrt(diag(object$cov.fixed))) if(s.has("random")) ans2 <- cbind(object$par.random, sqrt(as.numeric(object$diag.cov.random))) if(s.has("report")) ans3 <- cbind(object$value, object$sd) ans <- rbind(ans1, ans2, ans3) if(s.has("report")) { ans4 <- cbind("Est. (bias.correct)" = object$unbiased$value, "Std. (bias.correct)" = object$unbiased$sd) if(!is.null(ans4)) ans <- cbind(ans, rbind(NA * ans1, NA * ans2, ans4)) } if(length(ans) && ncol(ans) > 0) { colnames(ans)[1:2] <- c("Estimate", "Std. Error") if(p.value) { ans <- cbind(ans, "z value" = (z <- ans[,"Estimate"] / ans[,"Std. Error"])) ans <- cbind(ans, "Pr(>|z^2|)" = pchisq(z^2, df=1, lower.tail=FALSE)) } } else warning("no or empty summary selected via 'select = %s'", deparse(select)) ans } ##' Print parameter estimates and give convergence diagnostic based on ##' gradient and Hessian. ##' ##' @title Print brief model summary ##' @param x Output from \code{\link{sdreport}} ##' @param ... Not used ##' @return NULL ##' @method print sdreport ##' @S3method print sdreport print.sdreport <- function(x, ...) { cat("sdreport(.) result\n") print(summary(x, "fixed")) if(!x$pdHess) { cat("Warning:\nHessian of fixed effects was not positive definite.\n") } cat("Maximum gradient component:", max(abs(x$gradient.fixed)),"\n") invisible(x) } ##' Get estimated parameters or standard errors in the same shape as ##' the original parameter list. ##' ##' This function converts the selected column \code{what} of ##' \code{summary(x, select = c("fixed", "random"), ...)} to the same ##' format as the original parameter list (re-ordered as the template ##' parameter order). The argument \code{what} is partially matched ##' among the column names of the summary table. The actual match is ##' added as an attribute to the output. ##' ##' @title Convert estimates to original list format. ##' @param x Output from \code{\link{sdreport}}. ##' @param what Select what to convert (Estimate / Std. Error). ##' @param report Get AD reported variables rather than model parameters ? ##' @param ... Passed to \code{\link{summary.sdreport}}. ##' @return List of same shape as original parameter list. ##' @method as.list sdreport ##' @S3method as.list sdreport ##' @examples ##' \dontrun{ ##' example(sdreport) ##' ##' ## Estimates as a parameter list: ##' as.list(rep, "Est") ##' ##' ## Std Errors in the same list format: ##' as.list(rep, "Std") ##' ##' ## p-values in the same list format: ##' as.list(rep, "Pr", p.value=TRUE) ##' ##' ## AD reported variables as a list: ##' as.list(rep, "Estimate", report=TRUE) ##' ##' ## Bias corrected AD reported variables as a list: ##' as.list(rep, "Est. (bias.correct)", report=TRUE) ##' } as.list.sdreport <- function(x, what = "", report=FALSE, ...) { if (what == "") return (x) if (!report) { ans <- x$env$parameters random <- x$env$random par <- numeric(length(x$par.fixed) + length(x$par.random)) fixed <- rep(TRUE, length(par)) if(length(random)>0) fixed[random] <- FALSE ## Possible choices opts <- colnames( summary(x, select = c("fixed", "random"), ...) ) what <- match.arg(what, opts) if( any( fixed ) ) par[ fixed ] <- summary(x, select = "fixed", ...)[ , what] if( any(!fixed ) ) par[!fixed ] <- summary(x, select = "random", ...)[ , what] ## Workaround utils::relist bug (?) for empty list items nonemp <- sapply(ans, function(x)length(x) > 0) nonempindex <- which(nonemp) skeleton <- as.relistable(ans[nonemp]) li <- relist(par, skeleton) reshape <- function(x){ if(is.null(attr(x,"map"))) return(x) y <- attr(x,"shape") ## Handle special case where parameters are mapped to a fixed ## value if (what != "Estimate") { y[] <- NA } f <- attr(x,"map") i <- which(f >= 0) y[i] <- x[f[i] + 1L] y } for(i in seq(skeleton)){ ans[[nonempindex[i]]][] <- as.vector(li[[i]]) } for(i in seq(ans)){ ans[[i]] <- reshape(ans[[i]]) } } else { ## Reported variables ## Possible choices opts <- colnames( summary(x, select = "report", ...) ) what <- match.arg(what, opts) par <- summary(x, select = "report", ...)[ , what] skeleton <- lapply(x$env$ADreportDims, function(dim) array(NA, dim)) skeleton <- as.relistable(skeleton) ans <- relist(par, skeleton) ## Not keeping array dims ! ans <- Map(array, ans, x$env$ADreportDims) class(ans) <- NULL } attr(ans, "check.passed") <- NULL attr(ans, "what") <- what ans } TMB/R/TMB.R0000644000176200001440000024506014536066764011672 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ## Utilities grepRandomParameters <- function(parameters,random){ r <- sort(unique(unlist(lapply(random,function(regexp)grep(regexp,names(parameters)))))) tmp <- lapply(parameters,function(x)x*0) tmp[r] <- lapply(tmp[r],function(x)x*0+1) which(as.logical(unlist(tmp))) } ## unlist name handling is extremely slow and we *almost* never use it ## New default: use.names=FALSE unlist <- function (x, recursive = TRUE, use.names = FALSE) { base::unlist(x, recursive, use.names) } ## Assign without losing other attributes than 'names' (which may get ## overwritten when subsetting) "keepAttrib<-" <- function(x, value){ attr <- attributes(x) keep <- setdiff(names(attr), "names") x <- value attributes(x)[keep] <- attr[keep] x } ## Associate a 'map' with *one* entry in a parameter list updateMap <- function(parameter.entry, map.entry) { ## Shortened parameter ans <- tapply(parameter.entry, map.entry, mean) if(length(ans) == 0) ans <- as.numeric(ans) ## (zero-length case) ## Integer code used to fill short into original shape fnew <- unclass(map.entry) fnew[!is.finite(fnew)] <- 0L fnew <- fnew - 1L ## Output attr(ans,"shape") <- parameter.entry attr(ans,"map") <- fnew attr(ans,"nlevels") <- length(ans) ans } ## Guess name of user's loaded DLL code getUserDLL <- function(){ dlls <- getLoadedDLLs() isTMBdll <- function(dll)!is(try(getNativeSymbolInfo("MakeADFunObject",dll),TRUE),"try-error") TMBdll <- sapply(dlls, isTMBdll) if(sum(TMBdll) == 0) stop("There are no TMB models loaded (use 'dyn.load').") if(sum(TMBdll) >1 ) stop("Multiple TMB models loaded. Failed to guess DLL name.") names(dlls[TMBdll]) } ## Un-exported functions that we need .shlib_internal <- get(".shlib_internal", envir = asNamespace("tools"), inherits = FALSE) ## Update cholesky factorization ( of H+t*I ) avoiding copy overhead ## by writing directly to L(!). updateCholesky <- function(L, H, t=0){ .Call("tmb_destructive_CHM_update", L, H, t, PACKAGE="TMB") } solveCholesky <- function(L, x){ .Call("tmb_CHMfactor_solve", L, x, PACKAGE="TMB") } ## Test for invalid external pointer isNullPointer <- function(pointer) { .Call("isNullPointer", pointer, PACKAGE="TMB") } ## Add external pointer finalizer registerFinalizer <- function(ADFun, DLL) { if (is.null(ADFun)) return (NULL) ## ADFun=NULL used by sdreport ADFun$DLL <- DLL finalizer <- function(ptr) { if ( ! isNullPointer(ptr) ) { .Call("FreeADFunObject", ptr, PACKAGE=DLL) } else { ## Nothing to free } } reg.finalizer(ADFun$ptr, finalizer) ADFun } ##' Sequential reduction configuration ##' ##' Helper function to specify an integration grid used by the ##' sequential reduction algorithm available through the argument ##' \code{integrate} to \code{MakeADFun}. ##' @param x Breaks defining the domain of integration ##' @param discrete Boolean defining integration wrt Lebesgue measure (\code{discrete=FALSE}) or counting measure \code{discrete=TRUE}. SR <- function(x, discrete=FALSE) { if (is(x, "SR")) return (x) x <- as.numeric(x) if (is.unsorted(x)) stop("'x' must be sorted") if (discrete) { w <- rep(1., length(x)) } else { w <- diff(x) x <- head(x, -1) + w / 2 } structure(list(x=x, w=w, method="marginal_sr"), class="SR") } ##' Gauss Kronrod configuration ##' ##' Helper function to specify parameters used by the Gauss Kronrod ##' integration available through the argument \code{integrate} to ##' \code{MakeADFun}. ##' @param ... See source code GK <- function(...) { ans <- list(dim=1, adaptive=FALSE, debug=FALSE) args <- list(...) ans[names(args)] <- args ans$method <- "marginal_gk" class(ans) <- "GK" ans } ## TODO: Laplace approx config LA <- function(...) { ans <- list(...) ans$method <- "laplace" class(ans) <- "LA" ans } ## 'parse' MakeADFun argument 'integrate' parseIntegrate <- function(arg, name) { i <- sapply(arg, function(x) is(x, name)) arg[i] } ##' Construct objective functions with derivatives based on the users C++ template. ##' ##' A call to \code{MakeADFun} will return an object that, based on the users DLL code (specified through \code{DLL}), contains functions to calculate the objective function ##' and its gradient. The object contains the following components: ##' \itemize{ ##' \item \code{par} A default parameter. ##' \item \code{fn} The likelihood function. ##' \item \code{gr} The gradient function. ##' \item \code{report} A function to report all variables reported with the REPORT() macro in the user template. ##' \item \code{env} Environment with access to all parts of the structure. ##' } ##' and is thus ready for a call to an R optimizer, such as \code{nlminb} or \code{optim}. ##' Data (\code{data}) and parameters (\code{parameters}) are directly read by the user template via the macros beginning with DATA_ ##' and PARAMETER_. The order of the PARAMETER_ macros defines the order of parameters in the final objective function. ##' There are no restrictions on the order of random parameters, fixed parameters or data in the template. ##' @section Parameter mapping: ##' Optionally, a simple mechanism for collecting and fixing parameters from R is available through the \code{map} argument. A map is a named list ##' of factors with the following properties: ##' \itemize{ ##' \item names(map) is a subset of names(parameters). ##' \item For a parameter "p" length(map$p) equals length(parameters$p). ##' \item Parameter entries with NAs in the factor are fixed. ##' \item Parameter entries with equal factor level are collected to a common value. ##' } ##' More advanced parameter mapping, such as collecting parameters between different vectors etc., must be implemented from the template. ##' @section Specifying random effects: ##' Random effects are specified via the argument \code{random}: A component of the parameter list is marked as random if its name is matched ##' by any of the characters of the vector \code{random} (Regular expression match is performed if \code{regexp=TRUE}). ##' If some parameters are specified as random effects, these will ##' be integrated out of the objective function via the Laplace approximation. In this situation the functions \code{fn} and \code{gr} ##' automatically perform an optimization of random effects for each function evaluation. This is referred to as ##' the 'inner optimization'. Strategies for choosing initial values of the inner optimization can be controlled ##' via the argument \code{random.start}. The default is \code{expression(last.par.best[random])} ##' where \code{last.par.best} is an internal full parameter vector corresponding to the currently best ##' likelihood. An alternative choice could be \code{expression(last.par[random])} i.e. the random effect optimum of ##' the most recent - not necessarily best - likelihood evaluation. Further control of the inner optimization can ##' be obtained by the argument \code{inner.control} which is a list of control parameters for the inner optimizer ##' \code{newton}. Depending of the inner optimization problem type the following settings are recommended: ##' \enumerate{ ##' \item Quasi-convex: \code{smartsearch=TRUE} (the default). ##' \item Strictly-convex: \code{smartsearch=FALSE} and \code{maxit=20}. ##' \item Quadratic: \code{smartsearch=FALSE} and \code{maxit=1}. ##' } ##' @section The model environment \code{env}: ##' Technically, the user template is processed several times by inserting ##' different types as template parameter, selected by argument \code{type}: ##' \itemize{ ##' \item \code{"ADFun"} Run through the template with AD-types and produce a stack of operations representing the objective function. ##' \item \code{"Fun"} Run through the template with ordinary double-types. ##' \item \code{"ADGrad"} Run through the template with nested AD-types and produce a stack of operations representing the objective function gradient. ##' } ##' Each of these are represented by external pointers to C++ structures available in the environment \code{env}. ##' ##' Further objects in the environment \code{env}: ##' \itemize{ ##' \item \code{validpar} Function defining the valid parameter region (by default no restrictions). If an invalid ##' parameter is inserted \code{fn} immediately return NaN. ##' \item \code{parList} Function to get the full parameter vector of random and fixed effects in a convenient ##' list format. ##' \item \code{random} An index vector of random effect positions in the full parameter vector. ##' \item \code{last.par} Full parameter of the latest likelihood evaluation. ##' \item \code{last.par.best} Full parameter of the best likelihood evaluation. ##' \item \code{tracepar} Trace every likelihood evaluation ? ##' \item \code{tracemgc} Trace maximum gradient component of every gradient evaluation ? ##' \item \code{silent} Pass 'silent=TRUE' to all try-calls ? ##' } ##' @section The argument \code{intern}: ##' By passing \code{intern=TRUE} the entire Laplace approximation (including sparse matrix calculations) is done within the AD machinery on the C++ side. This requires the model to be compiled using the 'TMBad framework' - see \code{\link{compile}}. For any serious use of this option one should consider compiling with \code{supernodal=TRUE} - again see \code{\link{compile}} - in order to get performance comparable to R's matrix calculations. The benefit of the 'intern' LA is that it may be faster in some cases and that it provides an autodiff hessian (\code{obj$he}) wrt. the fixed effects which would otherwise not work for random effect models. Another benefit is that it gives access to fast computations with certain hessian structures that do not meet the usual sparsity requirement. A detailed list of options are found in the online doxygen documentation in the 'newton' namespace under the 'newton_config' struct. All these options can be passed from R via the `inner.control` argument. However, there are some drawbacks of running the LA on the C++ side. Notably, random effects are no longer visible in the model environment which may break assumptions on the layout of internal vectors (`par`, `last.par`, etc). In addition, model debugging becomes harder when calculations are moved to C++. ##' @section Controlling tracing: ##' A high level of tracing information will be output by default when evaluating the objective function and gradient. ##' This is useful while developing a model, but may eventually become annoying. Disable all tracing by passing ##' \code{silent=TRUE} to the \code{MakeADFun} call. ##' @note Do not rely upon the default arguments of any of the functions in the model object \code{obj$fn}, \code{obj$gr}, \code{obj$he}, \code{obj$report}. I.e. always use the explicit form \code{obj$fn(obj$par)} rather than \code{obj$fn()}. ##' ##' @title Construct objective functions with derivatives based on a compiled C++ template. ##' @param data List of data objects (vectors, matrices, arrays, factors, sparse matrices) required by the user template (order does not matter and un-used components are allowed). ##' @param parameters List of all parameter objects required by the user template (both random and fixed effects). ##' @param map List defining how to optionally collect and fix parameters - see details. ##' @param type Character vector defining which operation stacks are generated from the users template - see details. ##' @param random Character vector defining the random effect parameters. See also \code{regexp}. ##' @param profile Parameters to profile out of the likelihood (this subset will be appended to \code{random} with Laplace approximation disabled). ##' @param random.start Expression defining the strategy for choosing random effect initial values as function of previous function evaluations - see details. ##' @param hessian Calculate Hessian at optimum? ##' @param method Outer optimization method. ##' @param inner.method Inner optimization method (see function "newton"). ##' @param inner.control List controlling inner optimization. ##' @param MCcontrol List controlling importance sampler (turned off by default). ##' @param ADreport Calculate derivatives of macro ADREPORT(vector) instead of objective_function return value? ##' @param atomic Allow tape to contain atomic functions? ##' @param LaplaceNonZeroGradient Allow Taylor expansion around non-stationary point? ##' @param DLL Name of shared object file compiled by user (without the conventional extension, \file{.so}, \file{.dll}, \dots). ##' @param checkParameterOrder Optional check for correct parameter order. ##' @param regexp Match random effects by regular expressions? ##' @param silent Disable all tracing information? ##' @param intern Do Laplace approximation on C++ side ? See details (Experimental - may change without notice) ##' @param integrate Specify alternative integration method(s) for random effects (see details) ##' @param ... Currently unused. ##' @return List with components (fn, gr, etc) suitable for calling an R optimizer, such as \code{nlminb} or \code{optim}. MakeADFun <- function(data, parameters, map=list(), type=c("ADFun","Fun","ADGrad"[!intern && (!is.null(random) || !is.null(profile)) ] ), random=NULL, profile=NULL, random.start=expression(last.par.best[random]), hessian=FALSE,method="BFGS", inner.method="newton", inner.control=list(maxit=1000), MCcontrol=list(doMC=FALSE,seed=123,n=100), ADreport=FALSE, atomic=TRUE, LaplaceNonZeroGradient=FALSE, ## Experimental feature: Allow expansion around non-stationary point DLL=getUserDLL(), checkParameterOrder=TRUE, ## Optional check regexp=FALSE, silent=FALSE, intern=FALSE, integrate=NULL, ...){ ## Check that DLL is loaded if ( ! DLL %in% names(getLoadedDLLs()) ) { stop(sprintf("'%s' was not found in the list of loaded DLLs. Forgot to dyn.load(dynlib('%s')) ?", DLL, DLL)) } env <- environment() ## This environment if(!is.list(data)) stop("'data' must be a list") ok <- function(x)(is.matrix(x)|is.vector(x)|is.array(x))&(is.numeric(x)|is.logical(x)) ok.data <- function(x)ok(x)|is.factor(x)|is(x,"sparseMatrix")|is.list(x)|(is.character(x)&length(x)==1) check.passed <- function(x){ y <- attr(x,"check.passed") if(is.null(y)) FALSE else y } if(!check.passed(data)){ if(!all(sapply(data,ok.data))){ cat("Problem with these data entries:\n") print(which(!sapply(data,ok.data))) stop("Only numeric matrices, vectors, arrays, ", "factors, lists or length-1-characters ", "can be interfaced") } } if(!check.passed(parameters)){ if(!all(sapply(parameters,ok))){ cat("Problem with these parameter entries:\n") print(which(!sapply(parameters,ok))) stop("Only numeric matrices, vectors and arrays ", "can be interfaced") } } if(length(data)){ dataSanitize <- function(x){ if(is.list(x)) return( lapply(x, dataSanitize) ) if(is(x,"sparseMatrix")){ ## WAS: x <- as(x, "dgTMatrix") x <- as( as(x, "TsparseMatrix"), "generalMatrix") } else if (is.character(x)) { ## Do nothing } else { if(is.factor(x))x <- unclass(x)-1L ## Factors are passed as 0-based integers !!! storage.mode(x) <- "double" } x } if(!check.passed(data)){ data <- lapply(data,dataSanitize) } attr(data,"check.passed") <- TRUE } if(length(parameters)){ parameterSanitize <- function(x){ storage.mode(x) <- "double" x } if(!check.passed(parameters)){ parameters <- lapply(parameters,parameterSanitize) } attr(parameters,"check.passed") <- TRUE } if(checkParameterOrder){ ## For safety, check that parameter order match the parameter order in user template. ## If not, permute parameter list with a warning. ## Order in which parameters were requested: parNameOrder <- getParameterOrder(data, parameters, new.env(), DLL=DLL) if(!identical(names(parameters),parNameOrder)){ if(!silent) cat("Order of parameters:\n") if(!silent) print(names(parameters)) if(!silent) cat("Not matching template order:\n") if(!silent) print(parNameOrder) keepAttrib( parameters ) <- parameters[parNameOrder] if(!silent) cat("Your parameter list has been re-ordered.\n(Disable this warning with checkParameterOrder=FALSE)\n") } } ## Prepare parameter mapping. ## * A parameter map is a factor telling which parameters should be grouped ## * NA values are untouched: So user can e.g. set them to zero ## * NOTE: CURRENTLY ONLY WORKS ON PARAMETER_ARRAY() !!! if(length(map)>0){ ok <- all(names(map)%in%names(parameters)) if(!ok)stop("Names in map must correspond to parameter names") ok <- all(sapply(map,is.factor)) if(!ok)stop("map must contain factors") ok <- sapply(parameters[names(map)],length)==sapply(map,length) if(!all(ok))stop("A map factor length must equal parameter length") param.map <- lapply(names(map), function(nam) { updateMap(parameters[[nam]], map[[nam]]) }) ## Now do the change: keepAttrib( parameters[names(map)] ) <- param.map } lrandom <- function() { ans <- logical(length(par)) ans[random] <- TRUE ans } lfixed <- function() { !lrandom() } ## Utility to get back parameter list in original shape parList <- function(x=par[lfixed()],par=last.par){ ans <- parameters nonemp <- sapply(ans,function(x)length(x)>0) ## Workaround utils::relist bug for empty list items nonempindex <- which(nonemp) skeleton <- as.relistable(ans[nonemp]) par[lfixed()] <- x li <- relist(par,skeleton) reshape <- function(x){ if(is.null(attr(x,"map")))return(x) y <- attr(x,"shape") f <- attr(x,"map") i <- which(f>=0) y[i] <- x[f[i]+1] y } for(i in seq(skeleton)){ ans[[nonempindex[i]]][] <- as.vector(li[[i]]) } ## MM: ans[] <- lapply(ans, reshape) # _____________________ for(i in seq(ans)){ ans[[i]] <- reshape(ans[[i]]) } ans } type <- match.arg(type, eval(type), several.ok = TRUE) #if("ADFun"%in%type)ptrADFun <- .Call("MakeADFunObject",data,parameters) else ptrADFun <- NULL reportenv <- new.env() par <- NULL last.par.ok <- last.par <- last.par1 <- last.par2 <- last.par.best <- NULL value.best <- Inf ADFun <- NULL Fun <- NULL ADGrad <- NULL tracepar <- FALSE validpar <- function(x)TRUE tracemgc <- TRUE ## dummy assignments better than "globalVariables(....)" L.created.by.newton <- skipFixedEffects <- spHess <- altHess <- NULL ## Disable all tracing information beSilent <- function(){ tracemgc <<- FALSE inner.control$trace <<- FALSE silent <<- TRUE cf <- config(DLL=DLL) i <- grep("^trace.",names(cf)) cf[i] <- 0 cf$DLL <- DLL do.call(config, cf) NULL } if(silent)beSilent() ## Getting shape of ad reported variables ADreportDims <- NULL ADreportIndex <- function() { lngt <- sapply(ADreportDims, prod) offset <- head( cumsum( c(1, lngt) ) , -1) ans <- lapply(seq_along(lngt), function(i) array(seq(from = offset[i], length.out = lngt[i]), ADreportDims[[i]] )) names(ans) <- names(ADreportDims) ans } ## All external pointers are created in function "retape" and can be re-created ## by running retape() if e.g. the number of openmp threads is changed. ## set.defaults: reset internal parameters to their default values. .random <- random retape <- function(set.defaults = TRUE){ omp <- config(DLL=DLL) ## Get current OpenMP configuration random <<- .random ## Restore original 'random' argument if(atomic){ ## FIXME: Then no reason to create ptrFun again later ? ## User template contains atomic functions ==> ## Have to call "double-template" to trigger tape generation Fun <<- MakeDoubleFunObject(data, parameters, reportenv, DLL=DLL) ## Hack: unlist(parameters) only guarantied to be a permutation of the parameter vecter. out <- EvalDoubleFunObject(Fun, unlist(parameters), get_reportdims = TRUE) ADreportDims <<- attr(out, "reportdims") } if(is.character(profile)){ random <<- c(random, profile) } if(is.character(random)){ if(!regexp){ ## Default: do exact match if(!all(random %in% names(parameters))){ cat("Some 'random' effect names does not match 'parameter' list:\n") print(setdiff(random,names(parameters))) cat("(Note that regular expression match is disabled by default)\n") stop() } if(any(duplicated(random))){ cat("Duplicates in 'random' - will be removed\n") random <<- unique(random) } tmp <- lapply(parameters,function(x)x*0) tmp[random] <- lapply(tmp[random],function(x)x*0+1) random <<- which(as.logical(unlist(tmp))) if(length(random)==0) random <<- NULL } if(regexp){ ## Original regular expression match random <<- grepRandomParameters(parameters,random) if(length(random)==0){ cat("Selected random effects did not match any model parameters.\n") random <<- NULL } } if(is.character(profile)){ ## Convert 'profile' to a pointer into random (represented ## as logical index vector): tmp <- lapply(parameters,function(x)x*0) tmp[profile] <- lapply(tmp[profile],function(x)x*0+1) profile <<- match( which(as.logical(unlist(tmp))) , random ) if(length(profile)==0) random <<- NULL if(any(duplicated(profile))) stop("Profile parameter vector not unique.") tmp <- rep(0L, length(random)) tmp[profile] <- 1L profile <<- tmp } if (set.defaults) { par <<- unlist(parameters) } } if("ADFun"%in%type){ ## autopar? => Tape with single thread if (omp$autopar) openmp(1, DLL=DLL) ADFun <<- MakeADFunObject(data, parameters, reportenv, ADreport=ADreport, DLL=DLL) ## autopar? => Restore OpenMP number of threads if (omp$autopar) openmp(omp$nthreads, DLL=DLL) if (!is.null(integrate)) { nm <- sapply(parameters, length) nmpar <- rep(names(nm), nm) for (i in seq_along(integrate)) { I <- integrate[i] ## Special case: joint integration list if (is.null(names(I)) || names(I) == "") { I <- I[[1]] } ok <- all(names(I) %in% nmpar[random]) if (!ok) stop("Names to be 'integrate'd must be among the random parameters") w <- which(nmpar[random] %in% names(I)) ## Argument 'which' is common to all methods arg_which <- I[[1]]$which if ( ! is.null(arg_which) ) w <- w[arg_which] method <- sapply(I, function(x) x$method) ok <- all(duplicated(method)[-1]) if (!ok) stop("Grouping only allowed for identical methods") method <- method[1] cfg <- NULL if (method == "marginal_sr") { ## SR has special support for joint integration fac <- factor(nmpar[random[w]], levels=names(I)) cfg <- list( grid = I, random2grid = fac ) } else { ## For other methods we use the first ## (FIXME: Test no contradicting choices) cfg <- I[[1]] } stopifnot (is.list(cfg)) ## Integrate parameter subset out of the likelihood TransformADFunObject(ADFun, method = method, random_order = random[w], config = cfg, mustWork = 1L) ## Find out what variables have been integrated ## (only GK might not integrate all random[w]) activeDomain <- as.logical(info(ADFun)$activeDomain) random_remove <- random[w][!activeDomain[random[w]]] ## Integrated parameters must no longer be present TransformADFunObject(ADFun, method="remove_random_parameters", random_order = random_remove, mustWork = 1L) ## Adjust 'random' and 'par' accordingly attr(ADFun$ptr, "par") <- attr(ADFun$ptr, "par")[-random_remove] par_mask <- rep(FALSE, length(attr(ADFun$ptr, "par"))) par_mask[random] <- TRUE par <<- par[-random_remove] nmpar <- nmpar[-random_remove] par_mask <- par_mask[-random_remove] random <<- which(par_mask) if (length(random) == 0) { random <<- NULL type <<- setdiff(type, "ADGrad") } ## Run tape optimizer if (config(DLL=DLL)$optimize.instantly) { TransformADFunObject(ADFun, method = "optimize", mustWork = 1L) } } } if (intern) { cfg <- inner.control if (is.null(cfg$sparse)) cfg$sparse <- TRUE cfg <- lapply(cfg, as.double) TransformADFunObject(ADFun, method = "laplace", config = cfg, random_order = random, mustWork = 1L) TransformADFunObject(ADFun, method="remove_random_parameters", random_order = random, mustWork = 1L) ## FIXME: Should be done by above .Call attr(ADFun$ptr,"par") <- attr(ADFun$ptr,"par")[-random] ## par <<- par[-random] random <<- NULL ## Run tape optimizer if (config(DLL=DLL)$optimize.instantly) { TransformADFunObject(ADFun, method = "optimize", mustWork = 1L) } } if (set.defaults) { par <<- attr(ADFun$ptr,"par") last.par <<- par last.par1 <<- par last.par2 <<- par last.par.best <<- par value.best <<- Inf } } if (omp$autopar && !ADreport) { ## Experiment ! TransformADFunObject(ADFun, method = "parallel_accumulate", num_threads = as.integer(openmp(DLL=DLL)), mustWork = 0L) } if (length(random) > 0) { ## Experiment ! TransformADFunObject(ADFun, method = "reorder_random", random_order = random, mustWork = 0L) } if("Fun"%in%type) { Fun <<- MakeDoubleFunObject(data, parameters, reportenv, DLL=DLL) } if("ADGrad"%in%type) { retape_adgrad(lazy = TRUE) } ## Skip fixed effects from the full hessian ? ## * Probably more efficient - especially in terms of memory. ## * Only possible if a taped gradient is available - see function "ff" below. env$skipFixedEffects <- !is.null(ADGrad) delayedAssign("spHess", sparseHessianFun(env, skipFixedEffects=skipFixedEffects ), assign.env = env) }## end{retape} ## Lazy / Full adgrad ? retape_adgrad <- function(lazy = TRUE) { ## * Use already taped function value f = ADFun$ptr ## * In random effects case we only need the 'random' part of the gradient if (!lazy) random <- NULL ADGrad <<- MakeADGradObject(data, parameters, reportenv, random=random, f=ADFun$ptr, DLL=DLL) } retape(set.defaults = TRUE) ## Has atomic functions been generated for the tapes ? usingAtomics <- function().Call("usingAtomics", PACKAGE=DLL) .data <- NULL f <- function(theta=par, order=0, type="ADdouble", cols=NULL, rows=NULL, sparsitypattern=0, rangecomponent=1, rangeweight=NULL, dumpstack=0, doforward=1, do_simulate=0, set_tail=0, keepx=NULL, keepy=NULL) { if(isNullPointer(ADFun$ptr)) { if(silent)beSilent() ## Loaded or deep copied object: Only restore external ## pointers. Don't touch last.par/last.par.best etc: retape(set.defaults = FALSE) } ## User has changed the data => Next forward pass must traverse whole graph ! data_changed <- !identical(.data, data) ## Fast to check if identical (i.e. most of the time) if (data_changed) { .data <<- data ## Shallow copy (fast) } switch(type, "ADdouble" = { res <- EvalADFunObject(ADFun, theta, order=order, hessiancols=cols, hessianrows=rows, sparsitypattern=sparsitypattern, rangecomponent=rangecomponent, rangeweight=rangeweight, dumpstack=dumpstack, doforward=doforward, set_tail=set_tail, data_changed=data_changed) last.par <<- theta if(order==1)last.par1 <<- theta if(order==2)last.par2 <<- theta }, "double" = { res <- EvalDoubleFunObject(Fun, theta, do_simulate=do_simulate) }, "ADGrad" = { res <- EvalADFunObject(ADGrad, theta, order=order, hessiancols=cols, hessianrows=rows, sparsitypattern=sparsitypattern, rangecomponent=rangecomponent, rangeweight=rangeweight, dumpstack=dumpstack, doforward=doforward, set_tail=set_tail, keepx=keepx, keepy=keepy, data_changed=data_changed) }, stop("invalid 'type'")) # end{ switch() } res } ## end{ f } h <- function(theta=par, order=0, hessian, L, ...) { if(order == 0) { ##logdetH <- determinant(hessian)$mod logdetH <- 2*determinant(L, sqrt=TRUE)$modulus ans <- f(theta,order=0) + .5*logdetH - length(random)/2*log(2*pi) if(LaplaceNonZeroGradient){ grad <- f(theta,order=1)[random] ans - .5* sum(grad * as.numeric( solveCholesky(L, grad) )) } else ans } else if(order == 1) { if(LaplaceNonZeroGradient)stop("Not correct for LaplaceNonZeroGradient=TRUE") ##browser() e <- environment(spHess) solveSubset <- function(L).Call("tmb_invQ",L,PACKAGE="TMB") solveSubset2 <- function(L).Call("tmb_invQ_tril_halfdiag",L,PACKAGE="TMB") ## FIXME: The following two lines are not efficient: ## 1. ihessian <- tril(solveSubset(L)) ## 2. diag(ihessian) <- .5*diag(ihessian) ## Make option to solveSubset to return lower triangular part ## with diagonal halved. As it is now the output of solveSubset is ## symm _with upper storage_ (!) (side effect of cholmod_ptranspose) ## therefore tril takes long time. Further, "diag<-" is too slow. ## FIXED! : ihessian <- solveSubset2(L) ## Profile case correction (1st order case only) if(!is.null(profile)){ ## Naive way: ## ihessian[profile,] <- 0 ## ihessian[,profile] <- 0 ## However, this would modify sparseness pattern and also not ## account for 'ihessian' being permuted: perm <- L@perm+1L ihessian <- .Call("tmb_sparse_izamd", ihessian, profile[perm], 0.0, PACKAGE="TMB") } ## General function to lookup entries A subset B. ## lookup.old <- function(A,B){ ## A <- as(tril(A),"dtTMatrix") ## B <- as(tril(B),"dtTMatrix") ## match(paste(A@i,A@j),paste(B@i,B@j)) ## } ## General function to lookup entries A in B[r,r] assuming pattern of A ## is subset of pattern of B[r,r]. lookup <- function(A,B,r=NULL){ A <- tril(A); B <- tril(B) B@x[] <- seq.int(length.out=length(B@x)) ## Pointers to full B matrix (Can have up to 2^31-1 non-zeros) if(!is.null(r)){ ## Goal is to get: ## B <- forceSymmetric(B) ## B <- B[r,r,drop=FALSE] ## However the internal Matrix code for ## "B[r,r,drop=FALSE]" creates temporary "dgCMatrix" ## thereby almost doubling the number of non-zeros. Need ## solution that works with max (2^31-1) non-zeros: B <- .Call("tmb_half_diag", B, PACKAGE="TMB") B <- tril( B[r,r,drop=FALSE] ) + tril( t(B)[r,r,drop=FALSE] ) } m <- .Call("match_pattern", A, B, PACKAGE="TMB") ## Same length as A@x with pointers to B@x B@x[m] } if(is.null(e$ind1)){ ## hessian: Hessian of random effect part only. ## ihessian: Inverse subset of hessian (same dim but larger pattern!). ## Hfull: Pattern of full hessian including fixed effects. if (!silent) cat("Matching hessian patterns... ") iperm <- invPerm(L@perm+1L) e$ind1 <- lookup(hessian,ihessian,iperm) ## Same dimensions e$ind2 <- lookup(hessian,e$Hfull,random) ## Note: dim(Hfull)>dim(hessian) ! if (!silent) cat("Done\n") } w <- rep(0,length.out=length(e$Hfull@x)) w[e$ind2] <- ihessian@x[e$ind1] ## Reverse mode evaluate ptr in rangedirection w ## now gives .5*tr(Hdot*Hinv) !! ## return as.vector( f(theta,order=1) ) + EvalADFunObject(e$ADHess, theta, order=1, rangeweight=w) }## order == 1 else stop(sprintf("'order'=%d not yet implemented", order)) } ## end{ h } ff <- function(par.fixed=par[-random], order=0, ...) { names(par.fixed) <- names(par[-random]) f0 <- function(par.random,order=0,...){ par[random] <- par.random par[-random] <- par.fixed res <- f(par,order=order,set_tail=random[1],...) switch(order+1,res,res[random],res[random,random]) } ## sparse hessian H0 <- function(par.random){ par[random] <- par.random par[-random] <- par.fixed #spHess(par)[random,random,drop=FALSE] spHess(par,random=TRUE,set_tail=random[1]) } if(inner.method=="newton"){ #opt <- newton(eval(random.start),fn=f0,gr=function(x)f0(x,order=1), # he=function(x)f0(x,order=2)) opt <- try( do.call("newton",c(list(par=eval(random.start), fn=f0, gr=function(x)f0(x,order=1), ##he=function(x)f0(x,order=2)), he=H0,env=env), inner.control) ), silent=silent ) if (inherits(opt, "try-error") || !is.finite(opt$value)) { if (order==0) return(NaN) if (order==1) stop("inner newton optimization failed during gradient calculation") stop("invalid 'order'") } } else { opt <- optim(eval(random.start),fn=f0,gr=function(x)f0(x,order=1), method=inner.method,control=inner.control) } par[random] <- opt$par par[-random] <- par.fixed ## Use alternative Hessian for log determinant? altHessFlag <- !is.null(altHess) if (altHessFlag) { altHess(TRUE) ## Enable alternative hessian on.exit(altHess(FALSE)) } ## HERE! - update hessian and cholesky if(!skipFixedEffects){ ## old way hess <- spHess(par) ## Full hessian hessian <- hess[random,random] ## Subset } else { hessian <- spHess(par,random=TRUE) } ## Profile case correction (0 and 1st order) if( !is.null(profile) ){ ## Naive way: ## hessian[profile, ] <- 0 ## hessian[, profile] <- 0 ## diag(hessian)[profile] <- 1 ## However, this would modify sparseness pattern: hessian <- .Call("tmb_sparse_izamd", hessian, profile, 1.0, PACKAGE="TMB") } ## Update Cholesky: if(inherits(env$L.created.by.newton,"dCHMsuper")){ L <- env$L.created.by.newton ##.Call("destructive_CHM_update",L,hessian,as.double(0),PACKAGE="Matrix") updateCholesky(L,hessian) } else L <- Cholesky(hessian,perm=TRUE,LDL=FALSE,super=TRUE) if(order==0){ res <- h(par,order=0,hessian=hessian,L=L) ## Profile case correction if(!is.null(profile)){ res <- res + sum(profile)/2*log(2*pi) } if(is.finite(res)){ if(res=1){ vec <- exp(I-M) p <- vec/sum(vec) i <- (p>0) p <- p[i] I1 <- apply(samples[,i,drop=FALSE],2,eval.target,order=1)[-random,,drop=FALSE] gr <- as.vector(I1 %*% p) if(order==1)return(gr) ## I1I1 <- t(apply(I1,1,function(x)x%*%t(x))) ## I2 <- t(apply(samples,1,function(x)eval.target(x,order=2)[-random,-random])) ## h <- colMeans(vec*(-I1I1+I2))/mean(vec)+as.vector(gr)%*%t(as.vector(gr)) ## if(order==2)return(h) } if(!is.null(phi)){ phival <- apply(samples,2,phi) if(is.null(dim(phival)))phival <- t(phival) p <- exp(I-M); p <- p/sum(p) ans <- phival %*% p return(ans) } value <- -log(mean(exp(I-M)))-M ci <- 1.96*sd(exp(I-M))/sqrt(n) attr(value,"confint") <- -log(mean(exp(I-M))+c(lower=ci,upper=-ci))-M if(keep){ attr(value,"samples") <- samples attr(value,"nlratio") <- -I } value } report <- function(par=last.par){ f(par,order=0,type="double") as.list(reportenv) } simulate <- function(par = last.par, complete = FALSE){ f(par, order = 0, type = "double", do_simulate = TRUE) sim <- as.list(reportenv) if(complete){ ans <- data ans[names(sim)] <- sim } else { ans <- sim } ans } ## return : list( ## Default parameter vector par = par[lfixed()], ## Objective function fn = function(x = last.par[lfixed()], ...) { if (tracepar) { cat("par:\n"); print(x) } if (!validpar(x)) return(NaN) if (is.null(random)) { ans <- f(x,order=0) if (!ADreport) { if (is.finite(ans) && ans < value.best) { last.par.best <<- x; value.best <<- ans } } } else { ans <- try({ if(MCcontrol$doMC){ ff(x, order=0) MC(last.par, n=MCcontrol$n, seed=MCcontrol$seed, order=0) } else ff(x,order=0) }, silent=silent) if (is.character(ans)) ans <- NaN } ans }, ## Gradient of objective function gr = function(x = last.par[lfixed()], ...) { if (is.null(random)) { ans <- f(x, order=1) } else { ans <- try( { if (MCcontrol$doMC) { ff(x,order=0) MC(last.par, n=MCcontrol$n, seed=MCcontrol$seed, order=1) } else ff(x,order=1) }, silent=silent) if(is.character(ans)) ans <- rep(NaN, length(x)) } if (tracemgc) cat("outer mgc: ", max(abs(ans)), "\n") ans }, ## Hessian of objective function he = function(x = last.par[lfixed()], atomic=usingAtomics()) { if (is.null(random)) { ## If no atomics on tape we have all orders implemented: if(!atomic) return( f(x,order=2) ) ## Otherwise, get Hessian as 1st order derivative of gradient: if(is.null(ADGrad)) retape_adgrad() return( f(x, type="ADGrad", order=1) ) } else { stop("Hessian not yet implemented for models with random effects.") } }, ## Other methods and flags hessian=hessian, method=method, retape=retape, env=env, report=report, simulate=simulate,...) }## end{ MakeADFun } ##' Free memory allocated on the C++ side by \code{MakeADFun}. ##' ##' @note ##' This function is normally not needed. ##' @details ##' An object returned by \code{MakeADFun} contains pointers to ##' structures allocated on the C++ side. These are managed by R's ##' garbage collector which for the most cases is sufficient. However, ##' because the garbage collector is unaware of the C++ object sizes, ##' it may fail to release memory to the system as frequently as ##' necessary. In such cases one can manually call ##' \code{FreeADFun(obj)} to release the resources. ##' @section Memory management: ##' Memory allocated on the C++ side by \code{MakeADFun} is ##' represented by external pointers. Each such pointer has an ##' associated 'finalizer' (see \code{reg.finalizer}) that deallocates ##' the external pointer when \code{gc()} decides the pointer is no ##' longer needed. Deallocated pointers are recognized on the R ##' side as external null pointers \code{}. This is ##' important as it provides a way to prevent the finalizers from ##' freeing pointers that have already been deallocated \emph{even if ##' the deallocation C-code has been unloaded}. ##' The user DLL maintains a list of all external pointers on the C ##' side. Three events can reduce the list: ##' \itemize{ ##' \item Garbage collection of an external pointer that is no longer needed (triggers corresponding finalizer). ##' \item Explicit deallocation of external pointers using \code{FreeADFun()} (corresponding finalizers are untriggered but harmless). ##' \item Unload/reload of the user's DLL deallocates all external pointers (corresponding finalizers are untriggered but harmless). ##' } ##' @title Free memory allocated on the C++ side by \code{MakeADFun}. ##' @param obj Object returned by \code{MakeADFun} ##' @return NULL ##' @examples ##' runExample("simple", thisR = TRUE) ## Create 'obj' ##' FreeADFun(obj) ## Free external pointers ##' obj$fn() ## Re-allocate external pointers FreeADFun <- function(obj) { free <- function(ADFun) { if (! is.null(ADFun) ) { if ( ! isNullPointer(ADFun$ptr) ) { .Call("FreeADFunObject", ADFun$ptr, PACKAGE = obj$env$DLL) } } } free(obj$env$Fun) free(obj$env$ADFun) free(obj$env$ADGrad) ADHess <- environment(obj$env$spHess)$ADHess free(ADHess) return(NULL) } .removeComments <- function(x){ x <- paste(x,collapse="\n") remlong <- function(x)gsub("/\\*.*?\\*/","",x) remshort <- function(x)gsub("//[^\n]*\n","\n",x) x <- remshort(remlong(x)) strsplit(x,"\n")[[1]] } isParallelTemplate <- function(file){ code <- readLines(file) code <- .removeComments(code) length(grep("^[ \t]*PARALLEL_",code))>0 || length(grep("^[ \t]*parallel_accumulator",code))>0 } isParallelDLL <- function(DLL) { attr( .Call("getFramework", PACKAGE = DLL), "openmp") } ##' Control number of OpenMP threads used by a TMB model. ##' ##' This function controls the number of parallel threads used by a TMB model compiled with OpenMP. ##' The number of threads is part of the configuration list \code{config()} of the DLL. ##' The value only affects parallelization of the DLL. It does \emph{not} affect BLAS/LAPACK specific parallelization which has to be specified elsewhere. ##' ##' When a DLL is loaded, the number of threads is set to 1 by default. ##' To activate parallelization you have to explicitly call \code{openmp(nthreads)} after loading the DLL. Calling \code{openmp(max=TRUE)} should normally pick up the environment variable \code{OMP_NUM_THREADS}, but this may be platform dependent. ##' ##' An experimental option \code{autopar=TRUE} can be set to parallelize models automatically. This requires the model to be compiled with \code{framework="TMBad"} and \code{openmp=TRUE} without further requirements on the C++ code. If the C++ code already has explicit parallel constructs these will be ignored if automatic parallelization is enabled. ##' @title Control number of OpenMP threads used by a TMB model. ##' @param n Requested number of threads, or \code{NULL} to just read the current value. ##' @param max Logical; Set n to OpenMP runtime value 'omp_get_max_threads()'? ##' @param autopar Logical; use automatic parallelization - see details. ##' @param DLL DLL of a TMB model. ##' @return Number of threads. openmp <- function(n=NULL, max=FALSE, autopar=NULL, DLL=getUserDLL()) { ## Set n to max possible value? if (max) { n <- .Call("omp_num_threads", NULL, PACKAGE="TMB") } ## Set n ? if (!is.null(n)) config(nthreads=n, DLL=DLL) ## Set autopar ? if (is.logical(autopar)) config(autopar=autopar, DLL=DLL) ## Return current value ans <- config(DLL=DLL)$nthreads names(ans) <- DLL attr(ans, "autopar") <- as.logical(config(DLL=DLL)$autopar) ans } ##' Compile a C++ template into a shared object file. OpenMP flag is set if the template is detected to be parallel. ##' ##' TMB relies on R's built in functionality to create shared libraries independent of the platform. ##' A template is compiled by \code{compile("template.cpp")}, which will call R's makefile with appropriate ##' preprocessor flags. ##' Compiler and compiler flags can be stored in a configuration file. In order of precedence either via ##' the file pointed at by R_MAKEVARS_USER or the file ~/.R/Makevars if it exists. ##' Additional configuration variables can be set with the \code{flags} and \code{...} arguments, which will override any ##' previous selections. ##' ##' @section Using a custom SuiteSparse installation: ##' Sparse matrix calculations play an important role in TMB. By default TMB uses a small subset of \code{SuiteSparse} available through the R package \code{Matrix}. This is sufficient for most use cases, however for some very large models the following extra features are worth considering: ##' ##' \itemize{ ##' \item Some large models benefit from an extended set of graph reordering algorithms (especially METIS) not part of \code{Matrix}. It is common that these orderings can provide quite big speedups. ##' \item Some large models need sparse matrices with number of nonzeros exceeding the current 32 bit limitation of \code{Matrix}. Normally such cases will result in the cholmod error 'problem too large'. \code{SuiteSparse} includes 64 bit integer routines to address this problem. ##' } ##' ##' Experimental support for linking to a \emph{custom} \code{SuiteSparse} installation is available through two arguments to the \code{\link{compile}} function. The first argument \code{supernodal=TRUE} tells TMB to use the supernodal Cholesky factorization from the system wide \code{SuiteSparse} on the C++ side. This will affect the speed of the Laplace approximation when run internally (using arguments \code{intern} or \code{integrate} to \code{\link{MakeADFun}}). ##' ##' The second argument \code{longint=TRUE} tells TMB to use 64 bit integers for sparse matrices on the C++ side. This works in combination with \code{supernodal=TRUE} from Eigen version 3.4. ##' ##' On Windows a \code{SuiteSparse} installation can be obtained using the \code{Rtools} package manager. Start 'Rtools Bash' terminal and run: ##' \preformatted{ ##' pacman -Sy ##' pacman -S mingw-w64-{i686,x86_64}-suitesparse ##' } ##' ##' On Linux one should look for the package \code{libsuitesparse-dev}. ##' ##' @section Selecting the AD framework: ##' TMB supports two different AD libraries 'CppAD' and 'TMBad' selected via the argument \code{framework} which works as a switch to set one of two C++ preprocessor flags: 'CPPAD_FRAMEWORK' or 'TMBAD_FRAMEWORK'. The default value of \code{framework} can be set from R by \code{options("tmb.ad.framework")} or alternatively from the shell via the environment variable 'TMB_AD_FRAMEWORK'. Packages linking to TMB should set one of the two C++ preprocessor flags in Makevars. ##' ##' @section Order of compiler generated atomic functions: ##' The argument \code{max.order} controls the maximum derivative order of special functions (e.g. \code{pbeta}) generated by the compiler. By default the value is set to 3 which is sufficient to obtain the Laplace approximation (order 2) and its derivatives (order 3). However, sometimes a higher value may be needed. For example \code{framework='TMBad'} allows one to calculate the Hessian of the Laplace approximation, but that requires 4th order derivatives of special functions in use. A too small value will cause the runtime error 'increase TMB_MAX_ORDER'. Note that compilation time and binary size increases with \code{max.order}. ##' ##' @title Compile a C++ template to DLL suitable for MakeADFun. ##' @param file C++ file. ##' @param flags Character with compile flags. ##' @param safebounds Turn on preprocessor flag for bound checking? ##' @param safeunload Turn on preprocessor flag for safe DLL unloading? ##' @param openmp Turn on openmp flag? Auto detected for parallel templates. ##' @param libtmb Use precompiled TMB library if available (to speed up compilation)? ##' @param libinit Turn on preprocessor flag to register native routines? ##' @param tracesweep Turn on preprocessor flag to trace AD sweeps? (Silently disables \code{libtmb}) ##' @param framework Which AD framework to use ('TMBad' or 'CppAD') ##' @param supernodal Turn on preprocessor flag to use supernodal sparse Cholesky/Inverse from system wide suitesparse library ##' @param longint Turn on preprocessor flag to use long integers for Eigen's SparseMatrix StorageIndex ##' @param eigen.disable.warnings Turn on preprocessor flag to disable nuisance warnings. Note that this is not allowed for code to be compiled on CRAN. ##' @param max.order Maximum derivative order of compiler generated atomic special functions - see details. ##' @param ... Passed as Makeconf variables. ##' @seealso \code{\link{precompile}} compile <- function(file,flags="",safebounds=TRUE,safeunload=TRUE, openmp=isParallelTemplate(file[1]),libtmb=TRUE, libinit=TRUE,tracesweep=FALSE,framework=getOption("tmb.ad.framework"), supernodal=FALSE,longint=FALSE, eigen.disable.warnings=TRUE, max.order=NULL, ...){ framework <- match.arg(framework, c("CppAD", "TMBad")) ## Handle extra list(...) arguments plus modifications dotargs <- list(...) CPPFLAGS <- PKG_LIBS <- CLINK_CPPFLAGS <- NULL ## Visible binding (CRAN) '%+=%' <- function(VAR, x) { VAR <- deparse(substitute(VAR)) dotargs[[VAR]] <<- paste(dotargs[[VAR]], x) } if(.Platform$OS.type=="windows"){ ## Overload system.file system.file <- function(...){ ans <- base::system.file(...) chartr("\\", "/", shortPathName(ans)) } } qsystem.file <- function(...) { paste0('"', system.file(...), '"') } ## Cannot use the pre-compiled library when enabling sweep tracing if (tracesweep) libtmb <- FALSE ## libtmb existence debug <- length(grep("-O0", flags)) && length(grep("-g", flags)) fpath <- system.file(paste0("libs", Sys.getenv("R_ARCH")), package="TMB") f <- paste0(fpath, "/libTMB", if (openmp) "omp" else if (debug) "dbg", ".cpp") libtmb <- libtmb && file.exists(f) if(libtmb) file <- c(file, f) ## Function to create temporary makevars, Note: ## * R_MAKEVARS_USER overrules all other Makevars in tools:::.shlib_internal oldmvuser <- mvuser <- Sys.getenv("R_MAKEVARS_USER",NA) if(is.na(oldmvuser)){ on.exit(Sys.unsetenv("R_MAKEVARS_USER")) } else { on.exit(Sys.setenv(R_MAKEVARS_USER=oldmvuser)) } if(is.na(mvuser) && file.exists(f <- path.expand("~/.R/Makevars"))) mvuser <- f if(!is.na(mvuser)){ cat("Note: Using Makevars in",mvuser,"\n") } makevars <- function(...){ file <- tempfile() args <- unlist(list(...), use.names=TRUE) txt <- paste(names(args),args,sep="=") if(!is.na(mvuser)){ if(file.exists(mvuser)){ txt <- c(readLines(mvuser),txt) } } writeLines(txt,file) Sys.setenv(R_MAKEVARS_USER=file) file } ## Check that libname is valid C entry. libname <- sub("\\.[^\\.]*$","",basename(file[1])) if(safeunload){ valid <- c(letters[1:26],LETTERS[1:26],0:9,"_") invalid <- setdiff(unique(strsplit(libname,"")[[1]]),valid) if(length(invalid)>0){ cat("Your library name has invalid characters:\n") print(invalid) cat("It is recommended to replace invalid characters by underscore.\n") cat("Alternatively compile with safeunload=FALSE (not recommended).\n") stop() } } ## On windows the DLL must be unloaded before compiling if(.Platform$OS.type=="windows"){ tr <- try(dyn.unload(dynlib(libname)),silent=TRUE) if(!is(tr,"try-error"))cat("Note: Library",paste0("'",dynlib(libname),"'"),"was unloaded.\n") } ## Includes and preprocessor flags specific for the template useRcppEigen <- !file.exists( system.file("include/Eigen",package="TMB") ) useContrib <- file.exists( system.file("include/contrib",package="TMB") ) ppflags <- paste(paste0("-I",qsystem.file("include",package="TMB")), paste0("-I",qsystem.file("include",package="RcppEigen"))[useRcppEigen], paste0("-I",qsystem.file("include/contrib",package="TMB"))[useContrib], "-DTMB_SAFEBOUNDS"[safebounds], "-DTMB_EIGEN_DISABLE_WARNINGS"[eigen.disable.warnings], paste0("-DLIB_UNLOAD=R_unload_",libname)[safeunload], "-DWITH_LIBTMB"[libtmb], paste0("-DTMB_LIB_INIT=R_init_",libname)[libinit], "-DCPPAD_FORWARD0SWEEP_TRACE"[tracesweep], paste0("-D",toupper(framework),"_FRAMEWORK") ) ## *Very* primitive guess of suitesparse configuration ## (If wrong set supernodal=FALSE and tweak manually) if (supernodal) { if (framework != "TMBad") stop("'supernodal=TRUE' only works when framework='TMBad'") CPPFLAGS %+=% "-DTMBAD_SUPERNODAL -DEIGEN_USE_BLAS -DEIGEN_USE_LAPACKE" PKG_LIBS %+=% if (.Platform$OS.type=="windows") "-lcholmod -lcolamd -lamd -lsuitesparseconfig -lopenblas $(SHLIB_OPENMP_CXXFLAGS)" else "-lcholmod" CLINK_CPPFLAGS %+=% if (.Platform$OS.type=="windows") "" else "-I/usr/include/suitesparse" } ## Long integer support if (longint) { CPPFLAGS %+=% if (.Platform$OS.type=="windows") "-DTMB_SPARSE_STORAGE_INDEX='long long'" else "-DTMB_SPARSE_STORAGE_INDEX='long int'" } ## TMB_MAX_ORDER if (!is.null(max.order)) { CPPFLAGS %+=% paste0("-DTMB_MAX_ORDER=", max.order) } ## Makevars specific for template mvfile <- makevars(PKG_CPPFLAGS=ppflags, PKG_LIBS=paste( "$(SHLIB_OPENMP_CXXFLAGS)"[openmp] ), PKG_CXXFLAGS="$(SHLIB_OPENMP_CXXFLAGS)"[openmp], CXXFLAGS=flags[flags!=""], ## Optionally override cxxflags dotargs ) on.exit(file.remove(mvfile),add=TRUE) status <- .shlib_internal(file) ## Was: tools:::.shlib_internal(file) if(status!=0) stop("Compilation failed") status } ##' Precompile the TMB library ##' ##' Precompilation can be used to speed up compilation of ##' templates. It is only necessary to run \code{precompile()} once, ##' typically right after installation of TMB. The function ##' \emph{prepares} TMB for precompilation, while the actual ##' pre-compilation takes place the first time you compile a model ##' after running \code{precompile()}. ##' ##' Note that the precompilation requires write access to the TMB ##' package folder. Three versions of the library will be prepared: ##' Normal, parallel and a debugable version. ##' ##' Precompilation works the same way on all platforms. The only known ##' side-effect of precompilation is that it increases the file size ##' of the generated binaries. ##' @title Precompile the TMB library in order to speed up compilation of templates. ##' @param all Precompile all or just the core parts of TMB ? ##' @param clean Remove precompiled libraries ? ##' @param trace Trace precompilation process ? ##' @param get.header Create files 'TMB.h' and 'TMB.cpp' in current working directory to be used as part of a project? ##' @param ... Not used. ##' @examples ##' \dontrun{ ##' ## Prepare precompilation ##' precompile() ##' ## Perform precompilation by running a model ##' runExample(all = TRUE) ##' } precompile <- function(all=TRUE, clean=FALSE, trace=TRUE, get.header=FALSE, ...){ owdir <- getwd() on.exit(setwd(owdir)) if (get.header) { ## TMB.h outfile <- paste(getwd(), "TMB.h", sep="/") code <- c( "#ifndef TMB_H", "#define TMB_H", "#ifdef TMB_PRECOMPILE", "#define TMB_PRECOMPILE_ATOMICS"[all], "#else", "#define HAVE_PRECOMPILED_ATOMICS"[all], "#define WITH_LIBTMB", "#endif", "#include ", precompileSource()[all], "#endif") writeLines(code, outfile) if(trace) message(outfile, " generated") ## TMB.cpp outfile <- paste(getwd(), "TMB.cpp", sep="/") code <- c( "#define TMB_PRECOMPILE", '#include "TMB.h"' ) writeLines(code, outfile) if(trace) message(outfile, " generated") } else { folder <- system.file(paste0("libs", Sys.getenv("R_ARCH")), package="TMB") setwd(folder) if(clean){ f <- dir(pattern = "^libTMB") if(length(f) && trace) cat("Removing:", f, "\n") file.remove(f) f <- system.file(paste0("include/precompile.hpp"), package="TMB") file.create(f) return(NULL) } ## Cleanup before applying changes: precompile(clean = TRUE) ## Precompile frequently used classes: outfile <- paste0(system.file("include", package="TMB"), "/precompile.hpp") if(all) writeLines(precompileSource(), outfile) code <- c( "#undef TMB_LIB_INIT", "#undef LIB_UNLOAD", "#undef WITH_LIBTMB", "#undef TMB_PRECOMPILE_ATOMICS", "#define TMB_PRECOMPILE_ATOMICS 1", "#pragma message \"Running TMB precompilation...\""[trace], "#include " ) writeLines(code, "libTMB.cpp") writeLines(code, "libTMBomp.cpp") writeLines(code, "libTMBdbg.cpp") if(trace) message("Precompilation sources generated") } } ##' Add the platform dependent dynlib extension. In order for examples ##' to work across platforms DLLs should be loaded by ##' \code{dyn.load(dynlib("name"))}. ##' ##' @title Add dynlib extension ##' @param name Library name without extension ##' @return Character dynlib <- function(name)paste0(name,.Platform$dynlib.ext) ##' Create a cpp template to get started. ##' ##' This function generates a C++ template with a header and include ##' statement. Here is a brief overview of the C++ syntax used to code ##' the objective function. For a full reference see the Doxygen ##' documentation (more information at the package URL). ##' ##' Macros to read data and declare parameters: ##' \tabular{lll}{ ##' \bold{Template Syntax} \tab \bold{C++ type} \tab \bold{R type} \cr ##' DATA_VECTOR(name) \tab vector \tab vector \cr ##' DATA_MATRIX(name) \tab matrix \tab matrix \cr ##' DATA_SCALAR(name) \tab Type \tab numeric(1) \cr ##' DATA_INTEGER(name) \tab int \tab integer(1) \cr ##' DATA_FACTOR(name) \tab vector \tab factor \cr ##' DATA_IVECTOR(name) \tab vector \tab integer \cr ##' DATA_SPARSE_MATRIX(name) \tab Eigen::SparseMatrix \tab dgTMatrix \cr ##' DATA_ARRAY(name) \tab array \tab array \cr ##' PARAMETER_MATRIX(name) \tab matrix \tab matrix \cr ##' PARAMETER_VECTOR(name) \tab vector \tab vector \cr ##' PARAMETER_ARRAY(name) \tab array \tab array \cr ##' PARAMETER(name) \tab Type \tab numeric(1) \cr ##' } ##' ##' Basic calculations: ##' \tabular{ll}{ ##' \bold{Template Syntax} \tab \bold{Explanation} \cr ##' REPORT(x) \tab Report x back to R \cr ##' ADREPORT(x) \tab Report x back to R with derivatives \cr ##' vector v(n1); \tab R equivalent of v=numeric(n1) \cr ##' matrix m(n1,n2); \tab R equivalent of m=matrix(0,n1,n2) \cr ##' array a(n1,n2,n3); \tab R equivalent of a=array(0,c(n1,n2,n3)) \cr ##' v+v,v-v,v*v,v/v \tab Pointwise binary operations \cr ##' m*v \tab Matrix-vector multiply \cr ##' a.col(i) \tab R equivalent of a[,,i] \cr ##' a.col(i).col(j) \tab R equivalent of a[,j,i] \cr ##' a(i,j,k) \tab R equivalent of a[i,j,k] \cr ##' exp(v) \tab Pointwise math \cr ##' m(i,j) \tab R equivalent of m[i,j] \cr ##' v.sum() \tab R equivalent of sum(v) \cr ##' m.transpose() \tab R equivalent of t(m) \cr ##' } ##' ##' Some distributions are available as C++ templates with syntax close to R's distributions: ##' \tabular{ll}{ ##' \bold{Function header} \tab \bold{Distribution} \cr ##' dnbinom2(x,mu,var,int give_log=0) \tab Negative binomial with mean and variance \cr ##' dpois(x,lambda,int give_log=0) \tab Poisson distribution as in R \cr ##' dlgamma(y,shape,scale,int give_log=0) \tab log-gamma distribution \cr ##' dnorm(x,mean,sd,int give_log=0) \tab Normal distribution as in R \cr ##' } ##' @title Create cpp template to get started. ##' @param file Optional name of cpp file. ##' @examples ##' template() template <- function(file=NULL){ x <- readLines(system.file("template.cpp",package="TMB")) if(!is.null(file)){ if(file.exists(file))stop("File '",file,"' exists") writeLines(x,file) } else cat(paste(x,collapse="\n")) } ##' Create a skeleton of required R-code once the cpp template is ready. ##' ##' @title Create minimal R-code corresponding to a cpp template. ##' @param file cpp template file. ##' @examples ##' file <- system.file("examples/simple.cpp", package = "TMB") ##' Rinterface(file) Rinterface <- function(file){ libname <- sub("\\.[^\\.]*$", "", basename(file)) x <- readLines(file) x <- .removeComments(x) items2list <- function(items){ if(length(items)==0)return("list(),") paste0("list(\n",paste(paste0(" ",items,"= "),collapse=",\n"),"\n ),") } ## Data dataregexp <- "^[ ]*DATA_.*?\\((.*?)\\).*" datalines <- grep(dataregexp,x,value=TRUE) dataitems <- sub(dataregexp,"\\1",datalines) ## Parameters parameterregexp <- "^[ ]*PARAMETER.*?\\((.*?)\\).*" parameterlines <- grep(parameterregexp,x,value=TRUE) parameteritems <- sub(parameterregexp,"\\1",parameterlines) libname <- paste0("\"",libname,"\"") txt <- c("library(TMB)", paste0("dyn.load(dynlib(",libname,"))"), "MakeADFun(", paste0(" data=",items2list(dataitems)), paste0(" parameters=",items2list(parameteritems)), paste0(" DLL=",libname), ")\n" ) cat(paste(txt,collapse="\n")) } ## Recommended settings: ## * General non-convex case: smartsearch=TRUE ## * Strictly convex case: smartsearch=FALSE and maxit=20 ## * Quadratic case: smartsearch=FALSE and maxit=1 ##' Generalized newton optimizer used for the inner optimization problem. ##' ##' If \code{smartsearch=FALSE} this function performs an ordinary newton optimization ##' on the function \code{fn} using an exact sparse hessian function. ##' A fixed stepsize may be controlled by \code{alpha} so that the iterations are ##' given by: ##' \deqn{u_{n+1} = u_n - \alpha f''(u_n)^{-1}f'(u_n)} ##' ##' If \code{smartsearch=TRUE} the hessian is allowed to become negative definite ##' preventing ordinary newton iterations. In this situation the newton iterations are performed on ##' a modified objective function defined by adding a quadratic penalty around the expansion point \eqn{u_0}: ##' \deqn{f_{t}(u) = f(u) + \frac{t}{2} \|u-u_0\|^2}{f_t(u) = f(u) + t/2 |u-u_0|^2} ##' This function's hessian ( \eqn{f''(u)+t I} ) is positive definite for \eqn{t} sufficiently ##' large. The value \eqn{t} is updated at every iteration: If the hessian is positive definite \eqn{t} is ##' decreased, otherwise increased. Detailed control of the update process can be obtained with the ##' arguments \code{ustep}, \code{power} and \code{u0}. ##' @title Generalized newton optimizer. ##' @param par Initial parameter. ##' @param fn Objective function. ##' @param gr Gradient function. ##' @param he Sparse hessian function. ##' @param trace Print tracing information? ##' @param maxit Maximum number of iterations. ##' @param tol Convergence tolerance. ##' @param alpha Newton stepsize in the fixed stepsize case. ##' @param smartsearch Turn on adaptive stepsize algorithm for non-convex problems? ##' @param mgcmax Refuse to optimize if the maximum gradient component is too steep. ##' @param super Supernodal Cholesky? ##' @param silent Be silent? ##' @param ustep Adaptive stepsize initial guess between 0 and 1. ##' @param power Parameter controlling adaptive stepsize. ##' @param u0 Parameter controlling adaptive stepsize. ##' @param grad.tol Gradient convergence tolerance. ##' @param step.tol Stepsize convergence tolerance. ##' @param tol10 Try to exit if last 10 iterations not improved more than this. ##' @param env Environment for cached Cholesky factor. ##' @param ... Currently unused. ##' @return List with solution similar to \code{optim} output. ##' @seealso \code{\link{newtonOption}} newton <- function (par,fn,gr,he, trace = 1, maxit = 100, tol = 1e-8, alpha = 1, smartsearch = TRUE, mgcmax = 1e60, super = TRUE, silent = TRUE, ustep = 1, ## Start out optimistic: Newton step power=.5, ## decrease=function(u)const*u^power u0=1e-4, ## Increase u=0 to this value grad.tol = tol, step.tol = tol, tol10 = 1e-3, ## Try to exit if last 10 iterations not improved much env=environment(), ...) { ## Test if a Cholesky factor is present inside the environment of "he" function. ## If not - create one... if(is.null(L <- env$L.created.by.newton)) { h.pattern <- he(par) ## Make sure Cholesky is succesful h.pattern@x[] <- 0 diag(h.pattern) <- 1 L <- env$L.created.by.newton <- Cholesky(h.pattern, super=super) } chol.solve <- function(h,g){ ##.Call("destructive_CHM_update",L,h,as.double(0),PACKAGE="Matrix") updateCholesky(L,h) as.vector(solveCholesky(L,g)) } ## optimize <- stats::optimize nam <- names(par) par <- as.vector(par) g <- h <- NULL ## pd.check: Quick test for hessian being positive definite iterate <- function(par,pd.check=FALSE) { if(pd.check){ if(is.null(h))return(TRUE) h <<- he(par) ## Make sure hessian is updated PD <- updateCholesky(L, h) return( PD ) } g <<- as.vector(gr(par)) if(any( !is.finite(g) ))stop("Newton dropout because inner gradient had non-finite components.") if(is.finite(mgcmax) && max(abs(g)) > mgcmax) stop("Newton dropout because inner gradient too steep.") if(max(abs(g))-m)){ ## h+t*I negative definite ustep <<- min(ustep,invphi(-m)) return(NaN) } } ## Passed... ## Now do more expensive check... ##ok <- !is.character(try( .Call("destructive_CHM_update",L,h,as.double(t),PACKAGE="Matrix") , silent=silent)) ok <- updateCholesky(L, h, t) if(!ok)return(NaN) dp <- as.vector(solveCholesky(L,g)) p <<- par-dp ans <- fn(p) if(gradient)attr(ans,"gradient") <- sum(solveCholesky(L,dp)*gr(p)) ans } ## Adaptive stepsize algorithm (smartsearch) phi <- function(u)1/u-1 invphi <- function(x)1/(x+1) fu <- function(u){f(phi(u))} ## ========== Functions controling the algorithm ## Important requirements: ## 1. increase(u) and decrease(u) takes values in [0,1] ## 2. increase(u)>u and decrease(u)1 when u->1 ## 4. decrease(u)->0 when u->0 ## Properties of algorithm: ## * ustep must converge towards 1 (because 1 <==> Positive definite hessian) ## power<1 - controls the boundary *repulsion* increase <- function(u)u0+(1-u0)*u^power ##decrease <- function(u)1-increase(1-u) ## Solve problem with accuracy when u apprach 0 decrease <- function(u)ifelse(u>1e-10,1-increase(1-u),(1-u0)*power*u) ##plot(increase,0,1,ylim=c(0,1));plot(decrease,0,1,add=TRUE);abline(0,1) ustep <<- increase(ustep) repeat{ fu.value <- fu(ustep) if(is.finite(fu.value)){ eps <- sqrt(.Machine$double.eps) if(fu.value>fnpar+eps){ if(ustep<=0)break ## Avoid trap ustep <<- decrease(ustep) } else break } else { if(ustep<=0)break ## Avoid trap ustep <<- decrease(ustep) } } if(trace>=1)cat("value:", fu.value,"mgc:",max(abs(g)), "ustep:", ustep ,"\n") return(p) } dpar <- chol.solve(h,g) ## ordinary newton if(trace>=1)cat("mgc:",max(abs(g)) ,"\n") par - alpha * dpar } norm <- function(x) sqrt(sum(x^2)) fn.history <- numeric(maxit) fail <- 0 for (i in seq_len(maxit)){ parold <- par if(trace>=1)cat("iter:",i," ") par <- iterate(par) fn.history[i] <- fn(par) if(i>10){ tail10 <- tail(fn.history[1:i],10) improve10 <- tail10[1] - tail10[length(tail10)] if(improve10=1)cat("Not improving much - will try early exit...") pd <- iterate(par,pd.check=TRUE) if(trace>=1)cat("PD hess?:",pd,"\n") if(pd)break fail <- fail+1 } } if(norm(par-parold)5){ stop("Newton drop out: Too many failed attempts.") } } pd <- iterate(par,pd.check=TRUE) if(!pd)stop("Newton failed to find minimum.") names(par) <- nam value <- fn(par) g <- gr(par) if(trace>=1)cat("mgc:",max(abs(g)),"\n") list(par=par,value=value,gradient=g,hessian=h,iterations=i) } ##' Inner-problem options can be set for a model object using this ##' function. ##' ##' @title Set newton options for a model object. ##' @param obj Object from \code{\link{MakeADFun}} for which to change settings. ##' @param ... Parameters for the \code{\link{newton}} optimizer to set. ##' @return List of updated parameters. newtonOption <- function(obj,...){ if(!is.environment(obj$env)){ stop("First argument to 'newtonOption' must be a model object (output from MakeADFun)") } x <- list(...) validOpts <- setdiff(names(formals(newton)), c("par","fn","gr","he","env","...")) inValidOpts <- setdiff(names(x), validOpts) if(length(inValidOpts) > 0){ stop("Invalid newton option(s):", paste0(" '",inValidOpts,"'")) } obj$env$inner.control[names(x)] <- x invisible( obj$env$inner.control ) } sparseHessianFun <- function(obj, skipFixedEffects=FALSE) { r <- obj$env$random if (length(r) == 0) return (NULL) skip <- if(skipFixedEffects) { ## Assuming that random effects comes first in parameter list, we can set ## skip <- as.integer(length(obj$env$par)-length(r)) ## ==number of fixed effects seq_along(obj$env$par)[-r] } else { integer(0) ## <-- Empty integer vector } ## ptr.list ADHess <- MakeADHessObject(obj$env$data, obj$env$parameters, obj$env$reportenv, gf=obj$env$ADGrad$ptr, skip=skip, ## <-- Skip this index vector of parameters DLL=obj$env$DLL) ## Experiment ! TransformADFunObject(ADHess, method = "reorder_random", random_order = r, mustWork = 0L) ev <- function(par, set_tail=0) { EvalADFunObject(ADHess, par, set_tail = set_tail) } n <- as.integer(length(obj$env$par)) M <- new("dsTMatrix", i = as.integer(attr(ADHess$ptr,"i")), j = as.integer(attr(ADHess$ptr,"j")), x = ev(obj$env$par), Dim = c(n,n), uplo = "L") Hfull <- as(M, "CsparseMatrix") ## WAS: as(M,"dsCMatrix") Hrandom <- Hfull[r,r,drop=FALSE] ## before returning the function, remove unneeded variables from the environment: rm(skip, n, M) function(par = obj$env$par, random=FALSE, set_tail=0) { if(!random) { Hfull@x[] <- ev(par) Hfull } else if(skipFixedEffects) { .Call("setxslot", Hrandom, ev(par), PACKAGE="TMB") } else { Hfull@x[] <- ev(par, set_tail=set_tail) Hfull[r,r] } } } ## Debugging utility: Check sparse hessian. ## By comparing with gradient differentiated in random direction. checkSparseHessian <- function(obj,par=obj$env$last.par, w = rnorm(length(par)), ## random direction plot=TRUE,...){ r <- obj$env$random w[-r] <- 0 res1 <- obj$env$f(par, order = 1, type = "ADGrad", rangeweight = w)[r] res2 <- (obj$env$spHess(par)%*%w)[r] res <- list(x=res1,y=res2) if(plot){ plot(res,...) abline(0,1,col="red") } invisible(res) } ##' Aggressively tries to reduce fill-in of sparse Cholesky factor by ##' running a full suite of ordering algorithms. NOTE: requires a ##' specialized installation of the package. More information is ##' available at the package URL. ##' ##' @title Run symbolic analysis on sparse Hessian ##' @param obj Output from \code{MakeADFun} ##' @return NULL runSymbolicAnalysis <- function(obj){ ok <- .Call("have_tmb_symbolic",PACKAGE="TMB") if(!ok){ cat("note: tmb_symbolic not installed\n") return(NULL) } h <- obj$env$spHess(random=TRUE) h@x[] <- 0 diag(h) <- 1 L <- .Call("tmb_symbolic",h,PACKAGE="TMB") obj$env$L.created.by.newton <- L NULL } ## url: Can be local or remote zipfile ## skip.top.level: Skips the top level of unzipped directory. install.contrib <- function(url, skip.top.level = FALSE) { owd <- getwd() on.exit(setwd(owd)) contrib.folder <- paste0(system.file("include",package="TMB"), "/contrib" ) if( !file.exists( contrib.folder ) ) { dir.create(contrib.folder) } zipfile <- tempfile(fileext = ".zip") if(file.exists(url)) { ## Local zip file file.copy(url, zipfile) } else { ## Remote zipfile download.file(url, destfile = zipfile) } tmp.folder <- tempfile() dir.create(tmp.folder) df <- unzip(zipfile, list=TRUE) unzip(zipfile, exdir = tmp.folder) setwd(tmp.folder) ## If unzipped archive is a single folder then strip "-master" from name if(length(dir()) == 1) { if(file_test("-d", dir())) { file.rename(dir(), sub("-master$","",dir())) } if(skip.top.level) setwd(dir()) } file.copy(dir(), contrib.folder, recursive=TRUE) file.remove(zipfile) unlink(tmp.folder, recursive=TRUE) cat("NOTE:",contrib.folder,"\n") dir(contrib.folder) } TMB/R/validation.R0000644000176200001440000010602214455504313013357 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ##' Calculate one-step-ahead (OSA) residuals for a latent variable ##' model. (\emph{Beta version; may change without notice}) ##' ##' Given a TMB latent variable model this function calculates OSA ##' standardized residuals that can be used for goodness-of-fit ##' assessment. The approach is based on a factorization of the joint ##' distribution of the \emph{observations} \eqn{X_1,...,X_n} into ##' successive conditional distributions. ##' Denote by ##' \deqn{F_n(x_n) = P(X_n \leq x_n | X_1 = x_1,...,X_{n-1}=x_{n-1} )} ##' the one-step-ahead CDF, and by ##' \deqn{p_n(x_n) = P(X_n = x_n | X_1 = x_1,...,X_{n-1}=x_{n-1} )} ##' the corresponding point probabilities (zero for continuous distributions). ##' In case of continuous observations the sequence ##' \deqn{\Phi^{-1}(F_1(X_1))\:,...,\:\Phi^{-1}(F_n(X_n))} ##' will be iid standard normal. These are referred to as the OSA residuals. ##' In case of discrete observations draw (unit) uniform variables ##' \eqn{U_1,...,U_n} and construct the randomized OSA residuals ##' \deqn{\Phi^{-1}(F_1(X_1)-U_1 p_1(X_1))\:,...,\:\Phi^{-1}(F_n(X_n)-U_n p_n(X_n))} ##' These are also iid standard normal. ##' ##' @section Choosing the method: ##' The user must specify the method used to calculate the residuals - see detailed list of method descriptions below. ##' We note that all the methods are based on approximations. While the default 'oneStepGaussianoffMode' often represents a good compromise between accuracy and speed, it cannot be assumed to work well for all model classes. ##' As a rule of thumb, if in doubt whether a method is accurate enough, you should always compare with the 'oneStepGeneric' which is considered the most accurate of the available methods. ##' \describe{ ##' \item{method="fullGaussian"}{ ##' This method assumes that the joint distribution of data \emph{and} ##' random effects is Gaussian (or well approximated by a ##' Gaussian). It does not require any changes to the user ##' template. However, if used in conjunction with \code{subset} ##' and/or \code{conditional} a \code{data.term.indicator} is required ##' - see the next method. ##' } ##' \item{method="oneStepGeneric"}{ ##' This method calculates the one-step conditional probability ##' density as a ratio of Laplace approximations. The approximation is ##' integrated (and re-normalized for improved accuracy) using 1D ##' numerical quadrature to obtain the one-step CDF evaluated at each ##' data point. The method works in the continuous case as well as the ##' discrete case (\code{discrete=TRUE}). ##' ##' It requires a specification of a \code{data.term.indicator} ##' explained in the following. Suppose the template for the ##' observations given the random effects (\eqn{u}) looks like ##' \preformatted{ ##' DATA_VECTOR(x); ##' ... ##' nll -= dnorm(x(i), u(i), sd(i), true); ##' ... ##' } ##' ##' Then this template can be augmented with a ##' \code{data.term.indicator = "keep"} by changing the template to ##' \preformatted{ ##' DATA_VECTOR(x); ##' DATA_VECTOR_INDICATOR(keep, x); ##' ... ##' nll -= keep(i) * dnorm(x(i), u(i), sd(i), true); ##' ... ##' } ##' ##' The new data vector (\code{keep}) need not be passed from \R. It ##' automatically becomes a copy of \code{x} filled with ones. ##' ##' Some extra parameters are essential for the method. ##' Pay special attention to the integration domain which must be set either via \code{range} (continuous case) or \code{discreteSupport} (discrete case). Both of these can be set simultanously to specify a mixed continuous/discrete distribution. For example, a non-negative distribution with a point mass at zero (e.g. the Tweedie distribution) should have \code{range=c(0,Inf)} and \code{discreteSupport=0}. ##' Several parameters control accuracy and appropriate settings are case specific. By default, a spline is fitted to the one-step density before integration (\code{splineApprox=TRUE}) to reduce the number of density evaluations. However, this setting may have negative impact on accuracy. The spline approximation can then either be disabled or improved by noting that \code{...} arguments are passed to \link{tmbprofile}: Pass e.g. \code{ystep=20, ytol=0.1}. ##' Finally, it may be useful to look at the one step predictive distributions on either log scale (\code{trace=2}) or natural scale (\code{trace=3}) to determine which alternative methods might be appropriate. ##' } ##' \item{method="oneStepGaussian"}{ ##' This is a special case of the generic method where the one step ##' conditional distribution is approximated by a Gaussian (and can ##' therefore be handled more efficiently). ##' } ##' \item{method="oneStepGaussianOffMode"}{ ##' This is an approximation of the "oneStepGaussian" method that ##' avoids locating the mode of the one-step conditional density. ##' } ##' \item{method="cdf"}{ ##' The generic method can be slow due to the many function ##' evaluations used during the 1D integration (or summation in the ##' discrete case). The present method can speed up this process but ##' requires more changes to the user template. The above template ##' must be expanded with information about how to calculate the ##' negative log of the lower and upper CDF: ##' \preformatted{ ##' DATA_VECTOR(x); ##' DATA_VECTOR_INDICATOR(keep, x); ##' ... ##' nll -= keep(i) * dnorm(x(i), u(i), sd(i), true); ##' nll -= keep.cdf_lower(i) * log( pnorm(x(i), u(i), sd(i)) ); ##' nll -= keep.cdf_upper(i) * log( 1.0 - pnorm(x(i), u(i), sd(i)) ); ##' ... ##' } ##' ##' The specialized members \code{keep.cdf_lower} and ##' \code{keep.cdf_upper} automatically become copies of \code{x} ##' filled with zeros. ##' } ##' } ##' ##' @title Calculate one-step-ahead (OSA) residuals for a latent variable model. ##' @param obj Output from \code{MakeADFun}. ##' @param observation.name Character naming the observation in the template. ##' @param data.term.indicator Character naming an indicator data variable in the template (not required by all methods - see details). ##' @param method Method to calculate OSA (see details). ##' @param subset Index vector of observations that will be added one by one during OSA. By default \code{1:length(observations)} (with \code{conditional} subtracted). ##' @param conditional Index vector of observations that are fixed during OSA. By default the empty set. ##' @param discrete Logical; Are observations discrete? (assumed FALSE by default). ##' @param discreteSupport Possible outcomes of discrete part of the distribution (\code{method="oneStepGeneric"} and \code{method="cdf"} only). ##' @param range Possible range of continuous part of the distribution (\code{method="oneStepGeneric"} only). ##' @param seed Randomization seed (discrete case only). If \code{NULL} the RNG seed is untouched by this routine (recommended for simulation studies). ##' @param parallel Run in parallel using the \code{parallel} package? ##' @param trace Logical; Trace progress? More options available for \code{method="oneStepGeneric"} - see details. ##' @param reverse Do calculations in opposite order to improve stability? (currently enabled by default for \code{oneStepGaussianOffMode} method only) ##' @param splineApprox Represent one-step conditional distribution by a spline to reduce number of density evaluations? (\code{method="oneStepGeneric"} only). ##' @param ... Control parameters for OSA method ##' @return \code{data.frame} with OSA \emph{standardized} residuals ##' in column \code{residual}. In addition, depending on the method, the output ##' includes selected characteristics of the predictive distribution (current row) given past observations (past rows), notably the \emph{conditional} ##' \describe{ ##' \item{mean}{Expectation of the current observation} ##' \item{sd}{Standard deviation of the current observation} ##' \item{Fx}{CDF at current observation} ##' \item{px}{Density at current observation} ##' \item{nll}{Negative log density at current observation} ##' \item{nlcdf.lower}{Negative log of the lower CDF at current observation} ##' \item{nlcdf.upper}{Negative log of the upper CDF at current observation} ##' } ##' \emph{given past observations}. ##' If column \code{randomize} is present, it indicates that randomization has been applied for the row. ##' @examples ##' ######################## Gaussian case ##' runExample("simple") ##' osa.simple <- oneStepPredict(obj, observation.name = "x", method="fullGaussian") ##' qqnorm(osa.simple$residual); abline(0,1) ##' ##' \dontrun{ ##' ######################## Poisson case (First 100 observations) ##' runExample("ar1xar1") ##' osa.ar1xar1 <- oneStepPredict(obj, "N", "keep", method="cdf", discrete=TRUE, subset=1:100) ##' qqnorm(osa.ar1xar1$residual); abline(0,1) ##' } oneStepPredict <- function(obj, ## Names of data objects (not all are optional) observation.name = NULL, data.term.indicator = NULL, method=c( "oneStepGaussianOffMode", "fullGaussian", "oneStepGeneric", "oneStepGaussian", "cdf"), subset = NULL, conditional = NULL, discrete = NULL, discreteSupport = NULL, range = c(-Inf, Inf), seed = 123, parallel = FALSE, trace = TRUE, reverse = (method == "oneStepGaussianOffMode"), splineApprox = TRUE, ... ){ if (missing(observation.name)) stop("'observation.name' must define a data component") if (!(observation.name %in% names(obj$env$data))) stop("'observation.name' must be in data component") method <- match.arg(method) if (is.null(data.term.indicator)){ if(method != "fullGaussian"){ stop(paste0("method='",method,"' requires a 'data.term.indicator'")) } } ## if (!missing(discreteSupport) && !missing(range)) ## stop("Cannot specify both 'discreteSupport' and 'range'") obs <- as.vector(obj$env$data[[observation.name]]) ## Argument 'discrete' if(is.null(discrete)){ ndup <- sum(duplicated(setdiff(obs, discreteSupport))) if(ndup > 0){ warning("Observations do not look continuous. Number of duplicates = ", ndup) stop("Please specify 'discrete=TRUE' or 'discrete=FALSE'.") } discrete <- FALSE ## Default } stopifnot(is.logical(discrete)) ## Handle partially discrete distributions randomize <- NULL partialDiscrete <- !discrete && !missing(discreteSupport) if (partialDiscrete) { if (! (method %in% c("cdf", "oneStepGeneric")) ) stop("Mixed discrete/continuous distributions are currently for 'cdf' and 'oneStepGeneric' methods only") if (missing(range) && method == "oneStepGeneric") stop("Mixed discrete/continuous distributions must specify 'range' of continuous part") randomize <- obs %in% discreteSupport } ## Using wrong method for discrete data ? if (discrete){ if (! (method %in% c("oneStepGeneric", "cdf")) ){ stop(paste0("method='",method,"' is not for discrete observations.")) } } ## Default subset/permutation: if(is.null(subset)){ subset <- 1:length(obs) subset <- setdiff(subset, conditional) } ## Check if(!is.null(conditional)){ if(length(intersect(subset, conditional)) > 0){ stop("'subset' and 'conditional' have non-empty intersection") } } unconditional <- setdiff(1:length(obs), union(subset, conditional)) ## Args to construct copy of 'obj' args <- as.list(obj$env)[intersect(names(formals(MakeADFun)), ls(obj$env))] ## Use the best encountered parameter for new object if(length(obj$env$random)) args$parameters <- obj$env$parList(par = obj$env$last.par.best) else args$parameters <- obj$env$parList(obj$env$last.par.best) ## Fix all non-random components of parameter list names.random <- unique(names(obj$env$par[obj$env$random])) names.all <- names(args$parameters) fix <- setdiff(names.all, names.random) map <- lapply(args$parameters[fix], function(x)factor(x*NA)) ran.in.map <- names.random[names.random %in% names(args$map)] if(length(ran.in.map)) map <- c(map, args$map[ran.in.map]) # don't overwrite random effects mapping args$map <- map ## Overwrite map ## Find randomeffects character args$random <- names.random args$regexp <- FALSE ## Do we need to change, or take derivatives wrt., observations? ## (search the code to see if a method uses "observation(k,y)" or ## just "observation(k)"). obs.are.variables <- (method != "cdf") ## Move data$name to parameter$name if necessary if (obs.are.variables) { args$parameters[observation.name] <- args$data[observation.name] args$data[observation.name] <- NULL } ## Make data.term.indicator in parameter list if(!is.null(data.term.indicator)){ one <- rep(1, length(obs)) zero <- rep(0, length(obs)) if(method=="cdf"){ args$parameters[[data.term.indicator]] <- cbind(one, zero, zero) } else { args$parameters[[data.term.indicator]] <- cbind(one) } ## Set attribute to tell the order of observations ord <- rep(NA, length(obs)) ord[conditional] <- 0 ## First (out of bounds) ord[subset] <- seq_along(subset) ord[unconditional] <- length(obs) + 1 ## Never (out of bounds) if (any(is.na(ord))) { stop("Failed to determine the order of obervations") } attr(args$parameters[[data.term.indicator]], "ord") <- as.double(ord - 1) } ## Pretend these are *not observed*: if(length(unconditional)>0){ if(is.null(data.term.indicator)) stop("Failed to disable some data terms (because 'data.term.indicator' missing)") args$parameters[[data.term.indicator]][unconditional, 1] <- 0 } ## Pretend these are *observed*: if(length(conditional)>0){ if(is.null(data.term.indicator)) stop("Failed to enable some data terms (because 'data.term.indicator' missing)") args$parameters[[data.term.indicator]][conditional, 1] <- 1 } ## Make map for observations and indicator variables: makeFac <- function(x){ fac <- as.matrix(x) fac[] <- 1:length(x) fac[conditional, ] <- NA fac[unconditional, ] <- NA fac[subset, ] <- 1:(length(subset)*ncol(fac)) ## Permutation factor(fac) } map <- list() if (obs.are.variables) map[[observation.name]] <- makeFac(obs) if(!is.null(data.term.indicator)){ map[[data.term.indicator]] <- makeFac(args$parameters[[data.term.indicator]]) } args$map <- c(args$map, map) ## New object be silent args$silent <- TRUE ## 'fullGaussian' does *not* use any of the following objects if (method != "fullGaussian") { ## Create new object newobj <- do.call("MakeADFun", args) ## Helper function to loop through observations: nm <- names(newobj$par) obs.pointer <- which(nm == observation.name) if(method=="cdf"){ tmp <- matrix(which(nm == data.term.indicator), ncol=3) data.term.pointer <- tmp[,1] lower.cdf.pointer <- tmp[,2] upper.cdf.pointer <- tmp[,3] } else { data.term.pointer <- which(nm == data.term.indicator) lower.cdf.pointer <- NULL upper.cdf.pointer <- NULL } observation <- local({ obs.local <- newobj$par i <- 1:length(subset) function(k, y=NULL, lower.cdf=FALSE, upper.cdf=FALSE){ ## Disable all observations later than k: obs.local[data.term.pointer[k must set nthreads=1 nthreads.restore <- TMB::openmp() on.exit( TMB::openmp( nthreads.restore ), add=TRUE) TMB::openmp(1) requireNamespace("parallel") # was library(parallel) lapply <- parallel::mclapply } ## Trace one-step functions tracefun <- function(k)if(trace)print(k) ## Apply a one-step method and generate common output assuming ## the method generates at least: ## * nll ## * nlcdf.lower ## * nlcdf.upper applyMethod <- function(oneStepMethod){ ord <- seq_along(subset) if (reverse) ord <- rev(ord) pred <- do.call("rbind", lapply(ord, oneStepMethod)) pred <- as.data.frame(pred)[ord, ] pred$Fx <- 1 / ( 1 + exp(pred$nlcdf.lower - pred$nlcdf.upper) ) pred$px <- 1 / ( exp(-pred$nlcdf.lower + pred$nll) + exp(-pred$nlcdf.upper + pred$nll) ) if(discrete || partialDiscrete){ if(!is.null(seed)){ ## Restore RNG on exit: Random.seed <- .GlobalEnv$.Random.seed on.exit(.GlobalEnv$.Random.seed <- Random.seed) set.seed(seed) } U <- runif(nrow(pred)) if (partialDiscrete) { pred$randomize <- randomize[subset] U <- U * pred$randomize } } else { U <- 0 } pred$residual <- qnorm(pred$Fx - U * pred$px) pred } ## ######################### CASE: oneStepGaussian if(method == "oneStepGaussian"){ p <- newobj$par newobj$fn(p) ## Test eval oneStepGaussian <- function(k){ tracefun(k) index <- subset[k] f <- function(y){ newobj$fn(observation(k, y)) } g <- function(y){ newobj$gr(observation(k, y))[obs.pointer[k]] } opt <- nlminb(obs[index], f, g) H <- optimHess(opt$par, f, g) c(observation=obs[index], mean=opt$par, sd=sqrt(1/H)) } ord <- seq_along(subset) if (reverse) ord <- rev(ord) pred <- do.call("rbind", lapply(ord, oneStepGaussian)) pred <- as.data.frame(pred)[ord, ] pred$residual <- (pred$observation-pred$mean)/pred$sd } ## ######################### CASE: oneStepGaussianOffMode if(method == "oneStepGaussianOffMode"){ p <- newobj$par newobj$fn(p) ## Test eval newobj$env$random.start <- expression({last.par[random]}) oneStepGaussian <- function(k){ tracefun(k) index <- subset[k] f <- function(y){ newobj$fn(observation(k, y)) } g <- function(y){ newobj$gr(observation(k, y))[obs.pointer[k]] } c(observation=obs[index], nll = f(obs[index]), grad = g(obs[index])) } ord <- seq_along(subset) if (reverse) ord <- rev(ord) pred <- do.call("rbind", lapply(ord, oneStepGaussian)) pred <- as.data.frame(pred)[ord, ] ################### Convert value and gradient to residual ## Need Lambert W function: x = W(x) * exp( W(x) ) , x > 0 ## Vectorized in x and tested on extreme cases W(.Machine$double.xmin) ## and W(.Machine$double.xmax). W <- function(x){ ## Newton: f(y) = y * exp(y) - x ## f'(y) = y * exp(y) + exp(y) rel.tol <- sqrt(.Machine$double.eps) logx <- log(x) fdivg <- function(y)(y - exp(logx - y)) / (1 + y) y <- pmax(logx, 0) while( any( abs( logx - log(y) - y) > rel.tol, na.rm=TRUE) ) { y <- y - fdivg(y) } y } getResid <- function(value, grad){ Rabs <- sqrt( W( exp( 2*(value - log(sqrt(2*pi)) + log(abs(grad))) ) ) ) R <- sign(grad) * Rabs R } nll0 <- newobj$fn(observation(0)) R <- getResid( diff( c(nll0, pred$nll) ), pred$grad ) M <- pred$observation - ifelse(pred$grad != 0, R * (R / pred$grad), 0) pred$mean <- M pred$residual <- R } ## ######################### CASE: oneStepGeneric OSG_continuous <- missing(discreteSupport) || partialDiscrete if((method == "oneStepGeneric") && OSG_continuous){ p <- newobj$par newobj$fn(p) ## Test eval newobj$env$value.best <- -Inf ## <-- Never overwrite last.par.best nan2zero <- function(x)if(!is.finite(x)) 0 else x ## Set default configuration for this method (modify with '...'): formals(tmbprofile)$ytol <- 10 ## Tail tolerance (increase => more tail) formals(tmbprofile)$ystep <- .5 ## Grid spacing (decrease => more accuracy) ## Handle discrete case if(discrete){ formals(tmbprofile)$h <- 1 integrate <- function(f, lower, upper, ...){ grid <- ceiling(lower):floor(upper) list( value = sum( f(grid) ) ) } } oneStepGeneric <- function(k){ tracefun(k) ans <- try({ index <- subset[k] f <- function(y){ newobj$fn(observation(k, y)) } nll <- f(obs[index]) ## Marginal negative log-likelihood newobj$env$last.par.best <- newobj$env$last.par ## <-- used by tmbprofile if (splineApprox) { slice <- tmbprofile(newobj, k, slice=TRUE, parm.range = range,...) spline <- splinefun(slice[[1]], slice[[2]], ties=mean) spline.range <- range(slice[[1]]) if (partialDiscrete) { ## Remove density evaluations of discrete part slice[[1]][slice[[1]] %in% discreteSupport] <- NA } } else { spline <- Vectorize(f) spline.range <- range slice <- NULL } if(trace >= 2){ plotfun <- function(slice, spline){ plot.range <- spline.range if (!is.finite(plot.range[1])) plot.range[1] <- min(obs) if (!is.finite(plot.range[2])) plot.range[2] <- max(obs) if (!is.null(slice)) plot(slice, type="p", level=NULL) plot(spline, plot.range[1], plot.range[2], add=!is.null(slice)) abline(v=obs[index], lty="dashed") } if(trace >= 3){ if (!is.null(slice)) slice$value <- exp( -(slice$value - nll) ) plotfun(slice, function(x)exp(-(spline(x) - nll))) } else plotfun(slice, spline) } F1 <- integrate(function(x)exp(-(spline(x) - nll)), spline.range[1], obs[index])$value F2 <- integrate(function(x)exp(-(spline(x) - nll)), obs[index] + discrete, spline.range[2])$value mean <- integrate(function(x)exp(-(spline(x) - nll)) * x, spline.range[1], spline.range[2])$value / (F1 + F2) ## Correction mean, F1 and F2 if (partialDiscrete) { ## Evaluate discrete part f.discrete <- sapply(discreteSupport, f) Pdis <- exp(-f.discrete + nll) ## mean correction mean <- mean * (F1 + F2) + sum(Pdis * discreteSupport) mean <- mean / (F1 + F2 + sum(Pdis)) ## F1 and F2 correction left <- discreteSupport <= obs[index] F1 <- F1 + sum(Pdis[left]) F2 <- F2 + sum(Pdis[!left]) } ## Was: ## F1 <- integrate(Vectorize( function(x)nan2zero( exp(-(f(x) - nll)) ) ), -Inf, obs[index])$value ## F2 <- integrate(Vectorize( function(x)nan2zero( exp(-(f(x) - nll)) ) ), obs[index], Inf)$value nlcdf.lower = nll - log(F1) nlcdf.upper = nll - log(F2) c(nll=nll, nlcdf.lower=nlcdf.lower, nlcdf.upper=nlcdf.upper, mean=mean) }) if(is(ans, "try-error")) ans <- NaN ans } pred <- applyMethod(oneStepGeneric) } ## ######################### CASE: oneStepDiscrete if((method == "oneStepGeneric") && !OSG_continuous){ p <- newobj$par newobj$fn(p) ## Test eval obs <- as.integer(round(obs)) if(is.null(discreteSupport)){ warning("Setting 'discreteSupport' to ",min(obs),":",max(obs)) discreteSupport <- min(obs):max(obs) } oneStepDiscrete <- function(k){ tracefun(k) ans <- try({ index <- subset[k] f <- function(y){ newobj$fn(observation(k, y)) } nll <- f(obs[index]) ## Marginal negative log-likelihood F <- Vectorize(function(x)exp(-(f(x) - nll))) (discreteSupport) F1 <- sum( F[discreteSupport <= obs[index]] ) F2 <- sum( F[discreteSupport > obs[index]] ) nlcdf.lower = nll - log(F1) nlcdf.upper = nll - log(F2) c(nll=nll, nlcdf.lower=nlcdf.lower, nlcdf.upper=nlcdf.upper) }) if(is(ans, "try-error")) ans <- NaN ans } pred <- applyMethod(oneStepDiscrete) } ## ######################### CASE: fullGaussian if(method == "fullGaussian"){ ## Same object with y random: args2 <- args args2$random <- c(args2$random, observation.name) ## Change map: Fix everything except observations fix <- data.term.indicator args2$map[fix] <- lapply(args2$map[fix], function(x)factor(NA*unclass(x))) newobj2 <- do.call("MakeADFun", args2) newobj2$fn() ## Test-eval to find mode mode <- newobj2$env$last.par GMRFmarginal <- function (Q, i, ...) { ind <- 1:nrow(Q) i1 <- (ind)[i] i0 <- setdiff(ind, i1) if (length(i0) == 0) return(Q) Q0 <- as(Q[i0, i0, drop = FALSE], "symmetricMatrix") L0 <- Cholesky(Q0, ...) ans <- Q[i1, i1, drop = FALSE] - Q[i1, i0, drop = FALSE] %*% solve(Q0, Q[i0, i1, drop = FALSE]) ans } h <- newobj2$env$spHess(mode, random=TRUE) i <- which(names(newobj2$env$par[newobj2$env$random]) == observation.name) Sigma <- solve( as.matrix( GMRFmarginal(h, i) ) ) res <- obs[subset] - mode[i] L <- t(chol(Sigma)) pred <- data.frame(residual = as.vector(solve(L, res))) } ## ######################### CASE: cdf if(method == "cdf"){ p <- newobj$par newobj$fn(p) ## Test eval newobj$env$random.start <- expression(last.par[random]) cdf <- function(k){ tracefun(k) nll <- newobj$fn(observation(k)) lp <- newobj$env$last.par nlcdf.lower <- newobj$fn(observation(k, lower.cdf = TRUE)) newobj$env$last.par <- lp ## restore nlcdf.upper <- newobj$fn(observation(k, upper.cdf = TRUE)) newobj$env$last.par <- lp ## restore c(nll=nll, nlcdf.lower=nlcdf.lower, nlcdf.upper=nlcdf.upper) } pred <- applyMethod(cdf) } pred } ## Goodness of fit residuals based on an approximate posterior ## sample. (\emph{Beta version; may change without notice}) ## ## Denote by \eqn{(u, x)} the pair of the true un-observed random effect ## and the data. Let a model specification be given in terms of the ## estimated parameter vector \eqn{\theta} and let \eqn{u^*} be a ## sample from the conditional distribution of \eqn{u} given ## \eqn{x}. If the model specification is correct, it follows that the ## distribution of the pair \eqn{(u^*, x)} is the same as the distribution ## of \eqn{(u, x)}. Goodness-of-fit can thus be assessed by proceeding as ## if the random effect vector were observed, i.e check that \eqn{u^*} ## is consistent with prior model of the random effect and that \eqn{x} ## given \eqn{u^*} agrees with the observation model. ## ## This function can carry out the above procedure for many TMB models ## under the assumption that the true posterior is well approximated by a ## Gaussian distribution. ## ## First a draw from the Gaussian posterior distribution \eqn{u^*} is ## obtained based on the mode and Hessian of the random effects given the ## data. ## This sample uses sparsity of the Hessian and will thus work for large systems. ## ## An automatic standardization of the sample can be carried out \emph{if ## the observation model is Gaussian} (\code{fullGaussian=TRUE}). In this ## case the prior model is obtained by disabling the data term and ## calculating mode and Hessian. A \code{data.term.indicator} must be ## given in order for this to work. Standardization is performed using ## the sparse Cholesky of the prior precision. ## By default, this step does not use a fill reduction permutation \code{perm=FALSE}. ## This is often superior wrt. to interpretation of the. ## the natural order of the parameter vector is used \code{perm=FALSE} ## which may be superior wrt. to interpretation. Otherwise ## \code{perm=TRUE} a fill-reducing permutation is used while ## standardizing. ## @references Waagepetersen, R. (2006). A Simulation-based Goodness-of-fit Test for Random Effects in Generalized Linear Mixed Models. Scandinavian journal of statistics, 33(4), 721-731. ## @param obj TMB model object from \code{MakeADFun}. ## @param observation.name Character naming the observation in the template. ## @param data.term.indicator Character naming an indicator data variable in the template. Only used if \code{standardize=TRUE}. ## @param standardize Logical; Standardize sample with the prior covariance ? Assumes all latent variables are Gaussian. ## @param as.list Output posterior sample, and the corresponding standardized residual, as a parameter list ? ## @param perm Logical; Use a fill-reducing ordering when standardizing ? ## @param fullGaussian Logical; Flag to signify that the joint distribution of random effects and data is Gaussian. ## @return List with components \code{sample} and \code{residual}. oneSamplePosterior <- function(obj, observation.name = NULL, data.term.indicator = NULL, standardize = TRUE, as.list = TRUE, perm = FALSE, fullGaussian = FALSE){ ## Draw Gaussian posterior sample tmp <- obj$env$MC(n=1, keep=TRUE, antithetic=FALSE) samp <- as.vector( attr(tmp, "samples") ) ## If standardize resid <- NULL if (standardize) { ## Args to construct copy of 'obj' args <- as.list(obj$env)[intersect(names(formals(MakeADFun)), ls(obj$env))] ## Use the best encountered parameter for new object args$parameters <- obj$env$parList(par = obj$env$last.par.best) ## Make data.term.indicator in parameter list obs <- obj$env$data[[observation.name]] nobs <- length(obs) zero <- rep(0, nobs) if ( ! fullGaussian ) args$parameters[[data.term.indicator]] <- zero ## Fix all non-random components of parameter list names.random <- unique(names(obj$env$par[obj$env$random])) names.all <- names(args$parameters) fix <- setdiff(names.all, names.random) map <- lapply(args$parameters[fix], function(x)factor(x*NA)) args$map <- map ## Overwrite map ## If 'fullGaussian == TRUE' turn 'obs' into a random effect if (fullGaussian) { names.random <- c(names.random, observation.name) args$parameters[[observation.name]] <- obs } ## Find randomeffects character args$random <- names.random args$regexp <- FALSE ## New object be silent args$silent <- TRUE ## Create new object newobj <- do.call("MakeADFun", args) ## Construct Hessian and Cholesky newobj$fn() ## Get Cholesky and prior mean ## FIXME: We are using the mode as mean. Consider skewness ## correction similar to 'bias.correct' in 'sdreport'. L <- newobj$env$L.created.by.newton mu <- newobj$env$last.par ## If perm == FALSE redo Cholesky with natural ordering if ( ! perm ) { Q <- newobj$env$spHess(mu, random=TRUE) L <- Matrix::Cholesky(Q, super=TRUE, perm=FALSE) } ## If 'fullGaussian == TRUE' add 'obs' to the sample if (fullGaussian) { tmp <- newobj$env$par * NA tmp[names(tmp) == observation.name] <- obs tmp[names(tmp) != observation.name] <- samp samp <- tmp } ## Standardize ( P * Q * P^T = L * L^T ) r <- samp - mu rp <- r[L@perm + 1] Lt <- Matrix::t( as(L, "sparseMatrix") ) resid <- as.vector( Lt %*% rp ) } if (as.list) { if (standardize) obj <- newobj par <- obj$env$last.par.best asList <- function(samp) { par[obj$env$random] <- samp samp <- obj$env$parList(par=par) nm <- unique(names(obj$env$par[obj$env$random])) samp[nm] } samp <- asList(samp) if (!is.null(resid)) resid <- asList(resid) } ans <- list() ans$sample <- samp ans$residual <- resid ans } if(FALSE) { library(TMB) runExample("MVRandomWalkValidation", exfolder="../../tmb_examples/validation") set.seed(1) system.time( qw <- TMB:::oneSamplePosterior(obj, "obs", "keep") ) qqnorm(as.vector(qw$residual$u)); abline(0,1) runExample("rickervalidation", exfolder="../../tmb_examples/validation") set.seed(1) system.time( qw <- TMB:::oneSamplePosterior(obj, "Y", "keep") ) qqnorm(as.vector(qw$residual$X)); abline(0,1) runExample("ar1xar1") set.seed(1) system.time( qw <- TMB:::oneSamplePosterior(obj, "N", "keep") ) qqnorm(as.vector(qw$residual$eta)); abline(0,1) } TMB/R/checker.R0000644000176200001440000003110214417511650012625 0ustar liggesusers##' Check consistency of various parts of a TMB implementation. ##' Requires that user has implemented simulation code for the data and ##' optionally random effects. (\emph{Beta version; may change without ##' notice}) ##' ##' This function checks that the simulation code of random effects and ##' data is consistent with the implemented negative log-likelihood ##' function. It also checks whether the approximate \emph{marginal} ##' score function is central indicating whether the Laplace ##' approximation is suitable for parameter estimation. ##' ##' Denote by \eqn{u} the random effects, \eqn{\theta} the parameters ##' and by \eqn{x} the data. The main assumption is that the user has ##' implemented the joint negative log likelihood \eqn{f_{\theta}(u,x)} ##' satisfying ##' \deqn{\int \int \exp( -f_{\theta}(u,x) ) \:du\:dx = 1} ##' It follows that the joint and marginal score functions are central: ##' \enumerate{ ##' \item \eqn{E_{u,x}\left[\nabla_{\theta}f_{\theta}(u,x)\right]=0} ##' \item \eqn{E_{x}\left[\nabla_{\theta}-\log\left( \int \exp(-f_{\theta}(u,x))\:du \right) \right]=0} ##' } ##' For each replicate of \eqn{u} and \eqn{x} joint and marginal ##' gradients are calculated. Appropriate centrality tests are carried ##' out by \code{\link{summary.checkConsistency}}. An asymptotic ##' \eqn{\chi^2} test is used to verify the first identity. Power of ##' this test increases with the number of simulations \code{n}. The ##' second identity holds \emph{approximately} when replacing the ##' marginal likelihood with its Laplace approximation. A formal test ##' would thus fail eventually for large \code{n}. Rather, the gradient ##' bias is transformed to parameter scale (using the estimated ##' information matrix) to provide an estimate of parameter bias caused ##' by the Laplace approximation. ##' ##' @section Simulation/re-estimation: ##' A full simulation/re-estimation study is performed when \code{estimate=TRUE}. ##' By default \link[stats]{nlminb} will be used to perform the minimization, and output is stored in a separate list component 'estimate' for each replicate. ##' Should a custom optimizer be needed, it can be passed as a user function via the same argument (\code{estimate}). ##' The function (\code{estimate}) will be called for each simulation as \code{estimate(obj)} where \code{obj} is the simulated model object. ##' Current default corresponds to \code{estimate = function(obj) nlminb(obj$par,obj$fn,obj$gr)}. ##' @title Check consistency and Laplace accuracy ##' @param obj Object from \code{MakeADFun} ##' @param par Parameter vector (\eqn{\theta}) for simulation. If ##' unspecified use the best encountered parameter of the object. ##' @param hessian Calculate the hessian matrix for each replicate ? ##' @param estimate Estimate parameters for each replicate ? ##' @param n Number of simulations ##' @param observation.name Optional; Name of simulated observation ##' @return List with gradient simulations (joint and marginal) ##' @seealso \code{\link{summary.checkConsistency}}, \code{\link{print.checkConsistency}} ##' @examples ##' \dontrun{ ##' runExample("simple") ##' chk <- checkConsistency(obj) ##' chk ##' ## Get more details ##' s <- summary(chk) ##' s$marginal$p.value ## Laplace exact for Gaussian models } checkConsistency <- function(obj, par = NULL, hessian = FALSE, estimate = FALSE, n = 100, observation.name = NULL ) { ## Optimizer if (!is.logical(estimate)) { Optimizer <- match.fun(estimate) estimate <- TRUE } else { Optimizer <- function(obj) nlminb(obj$par, obj$fn, obj$gr) } ## Args to construct copy of 'obj' args <- as.list(obj$env)[intersect(names(formals(MakeADFun)), ls(obj$env))] ## Determine parameter and full parameter to use r0 <- r <- obj$env$random if( is.null(par) ) { ## Default case: Optimization has been carried out by user if (is.null(obj$env$last.par.best)) { stop("'par' not specified.") } parfull <- obj$env$last.par.best if( any(r) ) par <- parfull[-r] else par <- parfull } else { ## Custom case: User specifies parameter vector (fixed effects) parfull <- obj$env$par if( any(r) ) parfull[-r] <- par else parfull <- par } ## Get names of random effects (excluding profiled parameters) if(any(obj$env$profile)) { r0 <- r[ ! as.logical(obj$env$profile) ] names.profile <- unique(names(parfull[r[as.logical(obj$env$profile)]])) } else { names.profile <- NULL } names.random <- unique(names(parfull[r0])) ## Use 'parfull' for new object args$parameters <- obj$env$parList(par, par = parfull) ## Fix all profiled parameters map.profile <- lapply(args$parameters[names.profile], function(x)factor(x*NA)) args$map <- c(args$map, map.profile) ## Find randomeffects character args$random <- names.random args$regexp <- FALSE ## Are we in 'fast' (no retape) mode ? fast <- !is.null(observation.name) if (fast) { ## Move data -> parameters ## Note: We really do need to know 'observation.name'. There ## could be other (deterministic) items in 'data'... args$parameters <- c(args$data[observation.name], args$parameters) args$data[observation.name] <- NULL } ## Create new object newobj <- do.call("MakeADFun", args) newobj0 <- newobj ## backup if (fast) { parobs <- names(newobj$par) %in% observation.name ## NOTE: Simulation is stored as part of 'newobj$env$par' expandpar <- function(par) { ## Incudes par fixed *and* simulation: ans <- newobj0$env$par[newobj0$env$lfixed()] ans[!parobs] <- par ans } ## FIXME: No 'obj$he()' in this object newobj <- list(fn=function(x)newobj0$fn(expandpar(x)), gr=function(x)newobj0$gr(expandpar(x))[!parobs], par=newobj0$par[!parobs], env=newobj0$env ) } doSim <- function(...) { simdata <- newobj0$simulate(newobj0$env$par, complete=TRUE) if (!fast) { newobj$env$data <- simdata } ## Check that random effects have been simulated haveRandomSim <- all( names.random %in% names(simdata) ) ## Set good inner starting values if (haveRandomSim) { if (fast) { for (nm in names.random) { newobj$env$par[names(newobj$env$par) == nm] <- simdata[[nm]] } } else { newobj$env$parameters[names.random] <- simdata[names.random] } } ## FIXME: Mapped random effects not supported (yet) for 'fast' approach if (!fast && haveRandomSim) { ## Snippet taken from MakeADFun to account for mapped parameters: map <- args$map[names(args$map) %in% names.random] if (length(map) > 0) { param.map <- lapply(names(map), function(nam) { updateMap(newobj$env$parameters[[nam]], map[[nam]]) }) keepAttrib(newobj$env$parameters[names(map)]) <- param.map } } if (fast) { ## Set simulated data for (nm in observation.name) { newobj$env$par[names(newobj$env$par) == nm] <- simdata[[nm]] } ## Set inits newobj$env$last.par.best <- newobj$env$par newobj$env$value.best <- Inf } else { ## This approach *must* redo Cholesky newobj$env$L.created.by.newton <- NULL newobj$env$retape() } ans <- list() if (haveRandomSim) { ans$gradientJoint <- newobj$env$f(order=1) if(!is.null(newobj$env$random)) ans$gradientJoint <- ans$gradientJoint[-newobj$env$random] if (fast) ans$gradientJoint <- ans$gradientJoint[!parobs] } ans$gradient <- newobj$gr(par) if (hessian) ans$hessian <- optimHess(par, newobj$fn, newobj$gr) if (estimate) { newobj$par <- par ## just in case... ans$objective.true <- newobj$fn(par) ans$estimate <- try(Optimizer(newobj)) } ans } ans <- lapply(seq_len(n), doSim) attr(ans, "par") <- par class(ans) <- "checkConsistency" ans } ##' Summarize output from \code{\link{checkConsistency}} ##' ##' @title Summarize output from \code{\link{checkConsistency}} ##' @param object Output from \code{\link{checkConsistency}} ##' @param na.rm Logical; Remove failed simulations ? ##' @param ... Not used ##' @return List of diagnostics ##' @method summary checkConsistency ##' @S3method summary checkConsistency summary.checkConsistency <- function(object, na.rm=FALSE, ...) { ans <- list() ans$par <- attr(object, "par") getMat <- function(name) { do.call("cbind", lapply(object, function(x) as.vector(x[[name]]))) } ans$gradientJoint <- getMat( "gradientJoint" ) ans$gradient <- getMat( "gradient" ) ## Check simulation check <- function(mat) { if(!is.matrix(mat)) return( list(p.value=NA, bias=NA) ) if (na.rm) { fail <- as.logical( colSums( !is.finite(mat) ) ) mat <- mat[, !fail, drop=FALSE] } mu <- rowMeans(mat) npar <- length(mu) nsim <- ncol(mat) bias <- p.value <- NULL if(nsim < npar) { stop("Too few simulations ", nsim, " compared to number of parameters ", npar) } ## Variance of score = Information H <- var(t(mat)) iH <- try(solve(H), silent=TRUE) if(is(iH, "try-error")) { warning("Failed to invert information matrix") bias <- attr(object, "par") * NA p.value <- NA } else { mu.scaled <- sqrt(nsim) * mu q <- as.vector( t(mu.scaled) %*% iH %*% mu.scaled ) p.value <- 1 - pchisq(q, df=npar) bias <- -iH %*% mu } bias <- as.vector(bias) names(bias) <- names(attr(object, "par")) list(p.value=p.value, bias=bias) } ans$joint <- check( ans$gradientJoint ) ans$marginal <- check( ans$gradient ) ## Simulation study have.estimate <- !is.null(object[[1]]$estimate) if (have.estimate) { getEstMat <- function(name) { do.call("cbind", lapply(object, function(x) as.vector(x$estimate[[name]]))) } est <- list() est$par <- t(getEstMat("par")) colnames(est$par) <- names(ans$par) est$par <- as.data.frame(est$par) est$objective <- drop(getEstMat("objective")) est$deviance <- 2 * ( drop(getMat("objective.true")) - est$objective ) est$deviance.p.value <- ks.test(est$deviance, "pchisq", df = length(ans$par))$p.value ans$convergence <- drop(getEstMat("convergence")) ## Set it ans$estimate <- est } ans } ##' Print diagnostics output from \code{\link{checkConsistency}} ##' ##' @title Print output from \code{\link{checkConsistency}} ##' @param x Output from \code{\link{checkConsistency}} ##' @param ... Not used ##' @return NULL ##' @method print checkConsistency ##' @S3method print checkConsistency print.checkConsistency <- function(x, ...) { s <- summary(x) cat("Parameters used for simulation:\n") print(s$par) cat("\n") cat("Test correct simulation (p.value):\n") print(s$joint$p.value) alpha <- .05 ## FIXME: Perhaps make option s$sim.ok <- ( s$joint$p.value > alpha ) if(is.na(s$sim.ok)) cat("Full simulation was not available\n") else if(!s$sim.ok) cat("Simulation does *not* appear to be correct !!!\n") else cat("Simulation appears to be correct\n") ## Check Laplace: cat("\n") cat("Estimated parameter bias:\n") print(s$marginal$bias) ## Estimate info: if (!is.null(s$estimate)) { cat("\n") cat("summary(.)$estimate contains:\n") print(names(s$estimate)) } invisible(x) } if(FALSE) { library(TMB) runExample("sam", exfolder="../../tmb_examples") set.seed(123) qw <- checkConsistency(obj, opt$par, n=100) print.checkConsistency(qw) runExample("ar1_4D", exfolder="../../tmb_examples") set.seed(123) qw <- checkConsistency(obj, opt$par, n=100) qw } TMB/R/setupRStudio.R0000644000176200001440000001323614113627760013706 0ustar liggesusers## Experimental RStudio integration setupRStudio <- function(file = "~/.Rprofile", snipRfile = "~/.R/snippets/r.snippets", snipCppfile = "~/.R/snippets/c_cpp.snippets") { on.exit( message("Please re-start RStudio for the changes to take place.") ) code <- ' ######## TMB - setup RStudio setHook(packageEvent("TMB", "onLoad"), function(...) { if("tools:rstudio" %in% search()) { tmb.env <- asNamespace("TMB") compile.orig <- tmb.env$compile unlockBinding("compile", tmb.env) ## Rstudio handle compilation errors: rs.env <- as.environment("tools:rstudio") tmb.env$compile <- function(file,...) { .Call("rs_sourceCppOnBuild", file, FALSE, FALSE) status <- try( compile.orig(file, ...) ) succeeded <- (status == 0) .Call("rs_sourceCppOnBuildComplete", succeeded, "") if(!succeeded) stop("Compilation failed") status } ## Bind "sourceCpp" button to TMB compile rcpp.env <- asNamespace("Rcpp") unlockBinding("sourceCpp", rcpp.env) rcpp.env$sourceCpp <- tmb.env$compile ## Auto completion needs TMB and Eigen on system includes if (.Platform$OS.type=="windows") { ## Overload system.file system.file <- function(...){ ans <- base::system.file(...) chartr("\\\\", "/", shortPathName(ans)) } } definc <- Sys.getenv("CPLUS_INCLUDE_PATH") tmbinc <- system.file("include", package="TMB") eiginc <- system.file("include", package="RcppEigen") inc <- c(definc, tmbinc, eiginc) inc <- paste(inc[inc != ""], collapse=.Platform$path.sep) Sys.setenv(CPLUS_INCLUDE_PATH = inc) } } ) ' mess <- c("You are about to setup Rstudio with TMB.", "Changes will be added to the file:", "", file, "") invisible(lapply(mess, cat, "\n")) getYesOrNo <- function() { repeat { ans <- readline("OK? (yes/no) ") if (ans %in% c("yes", "no")) break; message("Please say 'yes' or 'no'") } ans } ans <- getYesOrNo() if(ans == "yes") { ## Create ~/.Rprofile if not exists if (!file.exists(file)) file.create(file) ## Read ~/.Rprofile and remove change if previously made oldlines <- readLines(file) codelines <- strsplit(code,"\n")[[1]][-1] begin <- which(head(codelines, 1) == oldlines)[1] if (!is.na(begin)) { if (begin > 1) begin <- begin - 1 end <- which(tail(codelines, 1) == oldlines) end <- min(end[end>begin]) oldlines <- oldlines[-(begin:end)] message("Removing old changes from ", file) writeLines(oldlines, file) } message("Adding changes to ", file) cat(code, file=file, append=TRUE) } ## Experimental RStudio TMB snippet integration ## Gavin Fay & Andrea Havron ## rsnips <- getRsnips() headers <- grep("snippet",rsnips) rsnips[-headers] <- paste0("\t",rsnips[-headers]) cppsnips <- getCppsnips() cheaders <- grep("snippet",cppsnips) cppsnips[-cheaders] <- paste0("\t",cppsnips[-cheaders]) mess <- c("", "You are about to setup snippets for TMB.", "Changes will be added to the files:", "", snipRfile, snipCppfile, "") invisible(lapply(mess, cat, "\n")) ans <- getYesOrNo() if(ans == "yes") { if (file.exists(snipRfile) && any( grepl(rsnips[headers][1], readLines(snipRfile)) ) ) { message("Skipping because changes seem to have been made already.") } else { dir.create(dirname(snipRfile), showWarnings=FALSE, recursive=TRUE) if (!file.exists(snipRfile)) file.create(snipRfile) cat(paste(rsnips, collapse="\n"), file=snipRfile, append=TRUE) dir.create(dirname(snipCppfile), showWarnings=FALSE, recursive=TRUE) if(!file.exists(snipCppfile))file.create(snipCppfile) cat(paste(cppsnips, collapse="\n"), file=snipCppfile, append=TRUE) } } invisible(NULL) } ## R snippets, paste as text, replace \$ with \\$ getRsnips <- function() { snips <- ' snippet tmb.template ## Load TMB `r require(TMB)` library(TMB) ## Make C++ file TMB::template("${1:model_name}.cpp") ## Compile and load the model compile("${1:model_name}.cpp") dyn.load(dynlib("${1:model_name}")) ## Data and parameters data <- list(x=rivers) parameters <- list(mu=0, logSigma=0) ## Make a function object obj <- MakeADFun(data, parameters, DLL="${1:model_name}") ## Call function minimizer opt <- nlminb(obj\\$par, obj\\$fn, obj\\$gr) ## Get parameter uncertainties and convergence diagnostics sdr <- sdreport(obj) sdr ' strsplit(snips, "\n")[[1]][-1] } ## R snippets, paste as text, replace \$ with \\$ ## FIXME: C++ snippets doesn't seem to work getCppsnips <- function() { snips <- ' snippet tmb.template #include template Type objective_function::operator() () { DATA_VECTOR(x); PARAMETER(mu); PARAMETER(logSigma); Type f = 0; f -= dnorm(x, mu, exp(logSigma), true).sum(); return f; } ' strsplit(snips, "\n")[[1]][-1] } TMB/R/header_tool.R0000644000176200001440000001223614536066764013532 0ustar liggesusers## Header extraction (keep declaration - remove definition) declExtract <- function(x, level=2){ ## level of matching curly brackets to exclude x <- paste(x, "\n") x <- paste(x, collapse="") x <- strsplit(x,"")[[1]] y <- cumsum( (x=="{") - (x=="}") ) mark.left <- (y == level) & (x=="{") ## Begin { mark.right <- (y == level - 1) & (x=="}") ## End } x[y >= level] <- "" ## Discard x[mark.right] <- ";" x <- paste(x, collapse="") x <- strsplit(x, "\n")[[1]] ## Change e.g. "matrix(T1 x):Base(x);" to "matrix(T1 x);" x <- sub(")[ ]*:.*;",");",x) x } ## Template class extraction tclassExtract <- function(x){ from <- grep("^class|^struct", x) - 1 to <- grep("^};", x) from <- from[ findInterval(to, from) ] nm <- gsub("^[^ ]*[ ]*([^ ^{^:]*).*", "\\1", x[from+1]) ans <- Map("[", list(x), Map(":", from, to) ) names(ans) <- nm ans } ## Template class specialization tclassSpecialize <- function(y, type="double"){ if(length(type) > 1){ return( unlist(lapply(type, function(x)tclassSpecialize(y, x))) ) } typename <- sub("^template[ ]*.*","\\1",y[1]) y[1] <- "template <>" nm <- gsub("^[^ ]*[ ]*([^ ^{^:]*).*", "\\1", y[2]) y[2] <- sub(nm,paste0(nm,"<",type,">"),y[2]) y <- gsub(typename, type, y) y } ## template class precompilation (explicit instantiation) tclassInstantiate <- function(y, type = "double"){ nm <- gsub("(^[^ ]*[ ]*[^ ^{^:]*).*", "\\1", y[2]) paste0("template ", nm, "<", type,">;") } ## Macro extraction macroExtract <- function(x){ x <- paste(x, "\n") x <- paste(x, collapse="") x <- gsub("\\\\[ ]*\n","",x) x <- gsub("\t","",x) x <- strsplit(x, "\n")[[1]] x <- grep("^#define", x, value=TRUE) nm <- sub("#define ([^ ^(]*).*", "\\1", x) names(x) <- nm x } ## Cleanup source cleanup <- function(x){ x <- .removeComments(x) ## Remove comments x <- gsub("[ ]*$", "", x) ## Remove trailing whitespace x <- x[x != ""] ## Remove empty lines x } ######################################################## ## Example precompSource <- function( filename = "include/tmbutils/density.hpp", namespace = "density", classes = "MVNORM_t", types = c( "double ", ## "CppAD::AD ", ## "CppAD::AD > ", ## "CppAD::AD > > ", "TMBad::ad_aug"), macros = TRUE, append = FALSE ## Modify input file in place ) { ## density namespace x <- readLines( system.file(filename, package="TMB") ) tcl <- tclassExtract(x) dcl <- lapply(tcl, declExtract) spec <- lapply(dcl, tclassSpecialize, type = types) macro <- macroExtract(x) macros <- rep(macros, length.out = length(macro)) ans <- c( ## Begin namespace paste("namespace", namespace, "{")[!is.null(namespace)], ## macro-defines paste("#undef", names(macro))[macros], macro[macros], ## Explicit instantiation "#ifdef WITH_LIBTMB", unlist( spec[classes] ), "#endif", ## Precompiled version "#ifdef TMB_PRECOMPILE_ATOMICS", unlist( lapply(classes, function(name)tclassInstantiate(tcl[[name]], types) ) ), "#endif", ## Undefs paste("#undef", names(macro))[macros], ## End namespace "}"[!is.null(namespace)] ) names(ans) <- NULL ## Add header ans <- cleanup(ans) ans <- c("// Autogenerated - do not edit by hand", "//", "// -DWITH_LIBTMB : Extracts header declarations only.", "// -DTMB_PRECOMPILE_ATOMICS : Instantiations for precompilation.", ans) if (append) { writeLines(c(x, ans), system.file(filename, package="TMB") ) return(NULL) } ans } precompileSource <- function() { CppAD_types <- c( "double ", "CppAD::AD ", "CppAD::AD > ", "CppAD::AD > > ") TMBad_types <- c( "double ", "TMBad::ad_aug " ) ## TODO : ## ============================================== ## precompSource( ## filename = "include/tmbutils/vector.hpp", ## namespace = NULL, ## classes = c("vector", "matrix"), ## append = TRUE ) ## , ## precompSource( ## filename = "include/tmbutils/array.hpp", ## namespace = "tmbutils", ## classes = c("array"), ## macros = FALSE ) ## , ## ============================================== x <- c( ## Precompile using CppAD "#ifdef CPPAD_FRAMEWORK", precompSource( filename = "include/tmbutils/density.hpp", namespace = "density", classes = c("MVNORM_t", "GMRF_t"), types = CppAD_types ), "#endif", ## Precompile using TMBad "#ifdef TMBAD_FRAMEWORK", precompSource( filename = "include/tmbutils/density.hpp", namespace = "density", classes = c("MVNORM_t", "GMRF_t"), types = TMBad_types ), "#endif" ) x } TMB/R/examples.R0000644000176200001440000000504514113627760013051 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ##' Compile and run a test example (\code{runExample()} shows all available examples). ##' ##' @title Run one of the test examples. ##' @param name Character name of example. ##' @param all Run all the test examples? ##' @param thisR Run inside this R? ##' @param clean Cleanup before compile? ##' @param exfolder Alternative folder with examples. ##' @param dontrun Build only (don't run) and remove temporary object files ? ##' @param subarch Build in sub-architecture specific folder ? ##' @param ... Passed to \code{\link{compile}}. runExample <- function(name=NULL,all=FALSE,thisR=TRUE, clean=FALSE,exfolder=NULL, dontrun=FALSE, subarch=TRUE,...){ cwd <- getwd() on.exit(setwd(cwd)) if(is.null(exfolder))exfolder <- system.file("examples",package="TMB") setwd(exfolder) arch <- Sys.getenv("R_ARCH") if(arch != "" && subarch){ arch <- sub("/", "", arch) if( !file.exists(arch) ){ dir.create(arch) file.copy(dir(pattern="*.[cpp|R]"), arch) } setwd(arch) } validExamples <- function(){ f1 <- sub("\\.[^\\.]*$","",dir(pattern=".R$")) f2 <- sub("\\.[^\\.]*$","",dir(pattern=".cpp$")) intersect(f1,f2) } exnames <- validExamples() cppnames <- paste0(exnames,".cpp") ## Format info as text M <- max(nchar(exnames)) info <- sapply(cppnames,function(x){readLines(x)[[1]]}) info[substring(info,1,2)!="//"] <- "" info <- sub("^// *","",info) tmp <- gsub(" ","@",format(paste("\"",exnames,"\"",":",sep=""),width=M+4)) info <- paste(tmp,info,sep="") info <- strwrap(info, width = 60, exdent = M+4) info <- gsub("@"," ",info) if(all){ lapply(exnames,runExample, thisR=thisR,clean=clean,exfolder=exfolder, dontrun=dontrun,subarch=subarch,...) return(invisible(NULL)) } if(is.null(name)){ txt <- paste("Examples in " ,"\'",exfolder,"\':","\n\n",sep="") cat(txt) writeLines(info) return(invisible(exnames)) } if(clean){ cat("Cleanup:\n") file.remove(dynlib(name)) file.remove(paste0(name,".o")) } if(!file.exists(dynlib(name))){ cat("Building example",name,"\n") time <- system.time(compile(paste0(name,".cpp"),...)) cat("Build time",time["elapsed"],"seconds\n\n") if(dontrun)file.remove(paste0(name,".o")) } if(!dontrun){ cat("Running example",name,"\n") if(!thisR){ system(paste("R --vanilla < ",name,".R",sep="")) } else { source(paste(name,".R",sep=""),echo=TRUE) } } } TMB/R/tmbprofile.R0000644000176200001440000002151614527235235013400 0ustar liggesusers## Copyright (C) 2013-2015 Kasper Kristensen ## License: GPL-2 ##' Calculate 1D likelihood profiles wrt. single parameters or more ##' generally, wrt. arbitrary linear combinations of parameters ##' (e.g. contrasts). ##' ##' Given a linear combination \deqn{ t = \sum_{i=1}^n v_i \theta_i } of ##' the parameter vector \eqn{\theta}, this function calculates the ##' likelihood profile of \eqn{t}. By default \eqn{v} is a unit vector ##' determined from \code{name}. Alternatively the linear combination ##' may be given directly (\code{lincomb}). ##' ##' @title Adaptive likelihood profiling. ##' @param obj Object from \code{MakeADFun} that has been optimized. ##' @param name Name or index of a parameter to profile. ##' @param lincomb Optional linear combination of parameters to ##' profile. By default a unit vector corresponding to \code{name}. ##' @param h Initial adaptive stepsize on parameter axis. ##' @param ytol Adjusts the range of the likelihood values. ##' @param ystep Adjusts the resolution of the likelihood profile. ##' @param maxit Max number of iterations for adaptive algorithm. ##' @param slice Do slicing rather than profiling? ##' @param parm.range Valid parameter range. ##' @param adaptive Logical; Use adaptive step size? ##' @param trace Trace progress? (TRUE, or a numeric value of 1, ##' gives basic tracing: numeric values > 1 give more information) ##' @param ... Unused ##' @return data.frame with parameter and function values. ##' @seealso \code{\link{plot.tmbprofile}}, \code{\link{confint.tmbprofile}} ##' @examples ##' \dontrun{ ##' runExample("simple",thisR=TRUE) ##' ## Parameter names for this model: ##' ## beta beta logsdu logsd0 ##' ##' ## Profile wrt. sigma0: ##' prof <- tmbprofile(obj,"logsd0") ##' plot(prof) ##' confint(prof) ##' ##' ## Profile the difference between the beta parameters (name is optional): ##' prof2 <- tmbprofile(obj,name="beta1 - beta2",lincomb = c(1,-1,0,0)) ##' plot(prof2) ##' confint(prof2) ##' } tmbprofile <- function(obj, name, lincomb, h=1e-4, ytol=2, ystep=.1, maxit=ceiling(5*ytol/ystep), parm.range = c(-Inf, Inf), slice=FALSE, adaptive=TRUE, trace=TRUE,...){ ## Cleanup 'obj' when we exit from this function: restore.on.exit <- c("last.par.best", "random.start", "value.best", "last.par", "inner.control", "tracemgc") oldvars <- sapply(restore.on.exit, get, envir=obj$env, simplify=FALSE) restore.oldvars <- function(){ for(var in names(oldvars)) assign(var, oldvars[[var]], envir=obj$env) } on.exit(restore.oldvars()) ## Parameter estimate (thetahat) par <- obj$env$last.par.best if(!is.null(obj$env$random)) par <- par[-obj$env$random] ## Determine lincomb vector ('lincomb') if(missing(lincomb)){ if (missing(name)) stop("No 'name' or 'lincomb' specified") stopifnot(length(name) == 1) if(is.numeric(name)){ lincomb <- as.numeric(1:length(par)==name) name <- names(par)[name] } else if(is.character(name)){ if (sum(names(par)==name) != 1) stop("'name' is not unique") lincomb <- as.numeric(names(par)==name) } else stop("Invalid name argument") } else { if (missing(name)) name <- "parameter" } stopifnot(length(lincomb) == length(par)) ## Re-parameterize to direction plus (n-1)-dim-subspace ## theta = t*direction + C %*% s X <- Diagonal(length(lincomb)) i <- which(lincomb != 0)[1] X[i,] <- lincomb ## Linear indep. columns invX <- solve(X) direction <- invX[,i] C <- invX[,-i,drop=FALSE] ## Now t(lincomb) %*% C = 0 ! that <- sum( lincomb * par ) ## Start out with initial increment h and ytol. ## * Evaluate and store next function value x1=x0+h, y1=f(x1). ## * Repeat as long as abs(y1-y.init)0) { if (trace>1) cat("Profile displacement:",x*direction,"\n") cat("Profile value:",ans$objective,"\n") } ans$objective } } ## Robustify f against failure f.original <- f f <- function(x){ y <- try(f.original(x), silent=TRUE) if(is(y, "try-error")) y <- NA y } start <- NULL evalAlongLine <- function(h){ start <<- rep(0, length(par)-1) x <- 0; y <- f(x) if(slice)obj$env$random.start <- expression(last.par[random]) for(it in 1:maxit){ yinit <- y[1] xcurrent <- tail(x,1) ycurrent <- tail(y,1) xnext <- xcurrent+h if(xnext + that < parm.range[1]) { if (trace>1) cat("below minimum value: break\n") break } if( parm.range[2] < xnext + that) { if (trace>1) cat("above maximum value: break\n") break } ynext <- f(xnext) x <- c(x,xnext) y <- c(y,ynext) if( is.na(ynext) ) { if (trace>1) cat("y is NA: break\n") break } if( (ydiff <- abs(ynext-yinit)) > ytol ) { if (trace>1) cat(sprintf("delta y=%f > %f: break\n", ydiff,ytol)) break } if (adaptive) { speedMax <- ystep speedMin <- if(ynext >= yinit) ystep/4 ## 'tail-part' else ystep/8 ## 'center-part' => slow down if( abs(ynext-ycurrent) > speedMax ) { h <- h / 2 if (trace>1) cat(sprintf("halve step size (to %f)\n",h)) } if( abs(ynext-ycurrent) < speedMin ) { h <- h * 2 if (trace>1) cat(sprintf("double step size (to %f)\n",h)) } } } ans <- data.frame(x=x+that, y=y) names(ans) <- c(name,"value") ans } if (trace>1) cat("profile up\n") ans1 <- evalAlongLine(h) restore.oldvars() if (trace>1) cat("profile down\n") ans2 <- evalAlongLine(-h) ans <- rbind(ans1,ans2) ord <- order(ans[[1]]) ans <- ans[ord,] class(ans) <- c("tmbprofile", class(ans)) ans } ##' Plot (negative log) likelihood profile with confidence interval added. ##' ##' @title Plot likelihood profile. ##' @param x Output from \code{\link{tmbprofile}}. ##' @param type Plot type. ##' @param level Add horizontal and vertical lines depicting this confidence level (\code{NULL} disables the lines). ##' @param ... Additional plot arguments. ##' @return NULL ##' @method plot tmbprofile ##' @S3method plot tmbprofile plot.tmbprofile <- function(x,type="l",level=.95,...){ plot(as.data.frame(x), type=type, ...) if(!is.null(level)){ hline <- .5*qchisq(level,df=1) abline(h=hline+min(x$value), lty="dotted") abline(v=confint(x, level=level), lty="dotted") } } ##' Calculate confidence interval from a likelihood profile. ##' ##' @title Profile based confidence intervals. ##' @param object Output from \code{\link{tmbprofile}}. ##' @param parm Not used ##' @param level Confidence level. ##' @param ... Not used ##' @return Lower and upper limit as a matrix. ##' @method confint tmbprofile ##' @S3method confint tmbprofile confint.tmbprofile <- function (object, parm, level = 0.95, ...){ i <- which.min(object$value) left <- head(object, i) right <- tail(object, nrow(object)-i ) hline <- .5*qchisq(level,df=1) + object$value[i] lower <- approx(left[[2]], left[[1]], hline)$y upper <- approx(right[[2]], right[[1]], hline)$y ans <- t( c(lower=lower, upper=upper) ) rownames(ans) <- names(object)[1] ans } TMB/MD50000644000176200001440000006167214536106351011224 0ustar liggesusersc04aa268f61546acf39e2cf1fe3642be *DESCRIPTION d665ce2442482e9df102977db7cc7020 *NAMESPACE ca350ca7ea0ae29930319a39a6315e59 *NEWS 06770828bf23ad462887487b1ba1bbd8 *R/TMB.R 0a8a19e6bc5dd48d053735256258e36a *R/benchmark.R b8cc540513343dbfade07876fe7848b3 *R/checker.R 6ce0ba48512cfa7824baad58adc436c2 *R/config.R 0de18d8b332daf5a55af20a482d98855 *R/dotCall.R 9e8f5d2786cedbab6aba9ad3aa26b527 *R/examples.R 04ed8003df5448ec456a90e6ce07cc8f *R/gdbsource.R aa45c5c2da1bda046b923066ae9e4ed5 *R/graph_transform.R 17042171104125770fd9900126983ecb *R/header_tool.R 56a1295a4739058af563a19d03bc45d0 *R/normalize.R 2a6af00bd9af32a5fbfae722647b4358 *R/sdreport.R f0a8e9eeabfb6ba0886e510ffe17b1cf *R/setupRStudio.R 2d124db373ceaf3988cfd6bd53f0083c *R/tmbprofile.R 34f335bfe3adb0536565aa747f241ca9 *R/tmbroot.R 9aaf0db05e1e4f8f6705e21c97a86af7 *R/utils.R 8fb198e9443ddd5bbcc0ea60142bd5e0 *R/validation.R 55263dc844a9081c28174084618d2438 *R/zzz.R eb282d3bb0c3c979198c80bb8713b2aa *inst/CITATION 24a129cdf0e26106e1c4f0fa86e1561a *inst/COPYRIGHTS be8e72009af7b2c27b1aec05c34c67be *inst/examples/ar1xar1.R 7b3318922db5fc0e236db8286058d319 *inst/examples/ar1xar1.cpp b5eb0691a2f04a5e8a3a4ff00cfed546 *inst/examples/linreg_parallel.R 597ae40bbf47d8a3a688c9b8137295e9 *inst/examples/linreg_parallel.cpp cafc553645337e587a317b2b05a5addf *inst/examples/randomregression.R 9a3cad6f5006de7b29f4e81ef5d2b255 *inst/examples/randomregression.cpp 4a93414fd3a6eddaeb81e3d48980ed5e *inst/examples/simple.R 5bfe7e3858e94c1cbdfe82a19e2c56a0 *inst/examples/simple.cpp c16463bf03af3da3c2dfc6a78cf1ce16 *inst/include/EigenWarnings/DisableStupidWarnings d4f69ae8aa7da50bf3bb09b1fd598731 *inst/include/Rstream.hpp ceb999d5c3ebf4d7f4126b8543c4e77f *inst/include/TMB.hpp 0eaf7a635884892151adad37884575e9 *inst/include/TMBad/TMBad.cpp 481c2eb64c1927608bdb0cf504321f2d *inst/include/TMBad/TMBad.hpp 4d100ee9c1835ed1bc7d82d90e21290f *inst/include/TMBad/ad_blas.hpp 874a10de7bd0090b14fec2d7129f0c67 *inst/include/TMBad/checkpoint.hpp 25e8edd341c204ad49dbf2eff67fd13c *inst/include/TMBad/code_generator.hpp 20925597983a152bd719e16b1079abe2 *inst/include/TMBad/compile.hpp 05c6f4b2dff132d39560807329ab8f70 *inst/include/TMBad/compression.hpp 736ee93df9d8b6a817e750b513f4dfbb *inst/include/TMBad/config.hpp 11d7cb05b168cd082952ba8a2627b277 *inst/include/TMBad/eigen_numtraits.hpp 11d17faa33d4c5e7f6bead97c47c3ba0 *inst/include/TMBad/global.hpp 5e5751d29bf6657124c794c3c2df784a *inst/include/TMBad/graph2dot.hpp e3ea72e0669f0b68177acf2ab4ad1074 *inst/include/TMBad/graph_transform.hpp 11ed0f6676cccf23cd218a543dfe9b42 *inst/include/TMBad/integrate.hpp 78a2d08aa61056792cc75050c2c9fb88 *inst/include/TMBad/radix.hpp 84b60c784a28117d60040e3d3e5f4aa0 *inst/include/TMBad/tmbad_allow_comparison.hpp 36d27943c9a55a25bd2cfa3de32e2998 *inst/include/TMBad/vectorize.hpp 5f72b6e57eac7c7b51db3a459d7e2d5c *inst/include/Vectorize.hpp 1722ff25f1321ce2cc76bd1b211cde07 *inst/include/atomic_convolve.hpp 6c3c56ee7abc9018016414b4e73839c1 *inst/include/atomic_macro.hpp 6cccfc5826f53c22f3d8eeb28a30f869 *inst/include/atomic_math.hpp 315caa47e8fe25e4053348e4ac2b3b1b *inst/include/checkpoint_macro.hpp 1b4fb806a143a79d3034aa2080fddcd6 *inst/include/config.hpp 6e2a3b3bc4d28ec135dad5f39089c6be *inst/include/convenience.hpp 54ae3bd2c920f39a37e0ac1286b63135 *inst/include/convert.hpp 23c76f5ff819f106b7b5a3016f6a671a *inst/include/cppad/CMakeLists.txt 496717792a2f73e7442031d80860f784 *inst/include/cppad/COPYING 5d6052d773ced6c5c8138e66b7cab3a9 *inst/include/cppad/CheckNumericType.h 8d98f263e9f82ebf25f24d54444923d1 *inst/include/cppad/CheckSimpleVector.h dad2f1fb33b3a0a9c93bf1874dab615c *inst/include/cppad/CppAD.h 46df8127d9421a01bf7fe7027499c6fd *inst/include/cppad/CppAD_vector.h 9154e443717b144ee790e8bd4b1323e6 *inst/include/cppad/ErrorHandler.h 2d9ad14fdecf71b16c0882dc2529f8e3 *inst/include/cppad/LuFactor.h 0bd5f2802b48a4142277798883d1dffb *inst/include/cppad/LuInvert.h ec2ebb8ce4e33508114c9f865aa4ea82 *inst/include/cppad/LuSolve.h 7a7f423e186258ddae3e478a179c21f0 *inst/include/cppad/NearEqual.h 16a2ac02d4c549854a7b0ce18bfde453 *inst/include/cppad/OdeErrControl.h 6005ef0520340949e6e066a4204fc642 *inst/include/cppad/OdeGear.h fcafd4a42bebd806a9fa7b6462b34ec4 *inst/include/cppad/OdeGearControl.h 4d7270af9ef7d398a772ce8cceb57172 *inst/include/cppad/Poly.h 25424409605f05fc5cb117bed1bd3d6b *inst/include/cppad/PowInt.h 03e9910055dcc470946a90107f5e6914 *inst/include/cppad/RombergMul.h 4d3f438b1f2143837ed44eb4307b9039 *inst/include/cppad/RombergOne.h 9a2ec1b57859c304343e6e3f021d3583 *inst/include/cppad/Rosen34.h 6a2f3d6a62a5bdc315cd5ab19f09679d *inst/include/cppad/Runge45.h 9ca037ee938eb8036a4e08acac107c9f *inst/include/cppad/SpeedTest.h 781b232202223cbc422e3a738fa52b8b *inst/include/cppad/TrackNewDel.h c80a1b18583bfd6690cec8b2f478b029 *inst/include/cppad/base_require.hpp 291c59145c092bfa82a14b593a7b905f *inst/include/cppad/check_numeric_type.hpp 771a416d8f5c5a3db3343c6deed02bf3 *inst/include/cppad/check_simple_vector.hpp 5831ca7865d39c62507b115baf41574c *inst/include/cppad/configure.hpp 94c272e5bbb3db47e806909edba907c1 *inst/include/cppad/configure.hpp.in 03b8c187d213b1839ba4a4dec588f66e *inst/include/cppad/cppad.hpp f9bbc2f39373fc2cbf671afcafc7f9f9 *inst/include/cppad/elapsed_seconds.hpp a9b2e205016efc2ba661a28a09b2ee6a *inst/include/cppad/error_handler.hpp 68bdebc518f96b42cfcddfe7b49dfba5 *inst/include/cppad/example/base_adolc.hpp bc0648038820b845e04d2e4c538b274d *inst/include/cppad/example/cppad_eigen.hpp 37abc01f634bef10b18fce5fa3fefa39 *inst/include/cppad/example/eigen_plugin.hpp 89a1dbd1cda07aa0ceaf044b0ba28d4c *inst/include/cppad/example/matrix_mul.hpp 2d3e19e821c782a620e1525d47134e53 *inst/include/cppad/index_sort.hpp 70a956ce3b8b513c5b09cc3facd4db60 *inst/include/cppad/ipopt/solve.hpp cd60277a86b8ff454e188db277882ad1 *inst/include/cppad/ipopt/solve_callback.hpp ef6a1013ce71a227b11062b303045b7f *inst/include/cppad/ipopt/solve_result.hpp c88b9d5474365427cc5f2a9eebd24bc4 *inst/include/cppad/local/abort_recording.hpp eec1a9defc13c98552e08f6f9a2e3fbe *inst/include/cppad/local/abs.hpp 1a3332a208ff41e694cc8cbaef61ddce *inst/include/cppad/local/abs_op.hpp cf01ae3aaf4c87042577345ddb7967bb *inst/include/cppad/local/acos_op.hpp b0d993c700b39d02a23a47242d9aa699 *inst/include/cppad/local/ad.hpp 6cde33273fbdb74e8fbbdd9e1097b1a5 *inst/include/cppad/local/ad_assign.hpp 0d123c4a3b24ac3c77c450033c80e766 *inst/include/cppad/local/ad_binary.hpp af2d3ab04501d9f2090a0ea5922f5f42 *inst/include/cppad/local/ad_ctor.hpp 8e4bbdcd5e7283837773d89f05d0917d *inst/include/cppad/local/ad_fun.hpp 0af4cdc336831e7908f8b151eb631efa *inst/include/cppad/local/ad_io.hpp 352bb27cce466c5edbb7ab6b3e16aba8 *inst/include/cppad/local/ad_tape.hpp 73a58f315f9c54a37ce2df195563f033 *inst/include/cppad/local/ad_valued.hpp 6fd78851b3babc00717837c119cb0153 *inst/include/cppad/local/add.hpp 86e901a5ab85584cd8c1c196b8dc35a1 *inst/include/cppad/local/add_eq.hpp bb5c71858915761c8c7d080f3cf42759 *inst/include/cppad/local/add_op.hpp 27442953cb225989ffcac1f80d948939 *inst/include/cppad/local/arithmetic.hpp 111ac01ea2d7f9cea50f8ac14ae63cc4 *inst/include/cppad/local/asin_op.hpp 2b46dd38d2cebfe8031f674fae74cd22 *inst/include/cppad/local/atan2.hpp b5427a29c029d459726364d1baa12c69 *inst/include/cppad/local/atan_op.hpp 95c71ea3874da7201004e0d376f4a400 *inst/include/cppad/local/atomic_base.hpp 53793bed6e5442051fae4eca9c962955 *inst/include/cppad/local/base_complex.hpp 0b5b87b3c8c04746c626a1de173278d3 *inst/include/cppad/local/base_cond_exp.hpp c0373e2d9f6d4f111d17317437b7289d *inst/include/cppad/local/base_double.hpp ffc714bd69d99d6ffd1a7d0029849b6d *inst/include/cppad/local/base_float.hpp e28defec4dd8a2cb716f66eb73386a35 *inst/include/cppad/local/base_std_math.hpp 937e397b55084d56be20d4dc57b48bb5 *inst/include/cppad/local/bender_quad.hpp a28c1dfb298ed706a1d8f79f16ecc284 *inst/include/cppad/local/bool_fun.hpp be88b1e9e125c5c8fe8322089d71faf6 *inst/include/cppad/local/bool_valued.hpp 6bf63c9b8214ec1f7f3a2e00e0218068 *inst/include/cppad/local/capacity_order.hpp 00e0fb03f1aecc6b13a0dd1c9fc20895 *inst/include/cppad/local/checkpoint.hpp dfb6a4d6219e01daab975c870d319f3c *inst/include/cppad/local/color_general.hpp ded869d847310cc2adc32c112e88ac3c *inst/include/cppad/local/color_symmetric.hpp 454520445e2ef19ca202049ebe5d9c9a *inst/include/cppad/local/comp_op.hpp 0c41bac89f01efad961e2464e3bccc2b *inst/include/cppad/local/compare.hpp 8cf6457c761b01577c405c13891f08fa *inst/include/cppad/local/compute_assign.hpp d703c3aa965322762a5d6b494eea52be *inst/include/cppad/local/cond_exp.hpp 4c765797a5187daa23eedba40f3ed4d4 *inst/include/cppad/local/cond_op.hpp ac24ca67731cca9aff7432c481f32c84 *inst/include/cppad/local/config.h.in f968c675c2b750101b0cc885308431bf *inst/include/cppad/local/convert.hpp 78a7bc936dbb8485f583913ed25bfeee *inst/include/cppad/local/cos_op.hpp 86471158b0bc289609b252771ae1a3d6 *inst/include/cppad/local/cosh_op.hpp b288df3c1d2697183988fe107fe3e528 *inst/include/cppad/local/cppad_assert.hpp 9424bf3f7950367f03efa1652288bff1 *inst/include/cppad/local/cppad_colpack.cpp a46a73e54a74593c85e3c375563ef4a1 *inst/include/cppad/local/cppad_colpack.hpp e1f1b8e85fd856c15650f96adb27e867 *inst/include/cppad/local/cskip_op.hpp b420b69a1dc6dd8768533b51442a5d5d *inst/include/cppad/local/csum_op.hpp 7e1b28a7cad1d4ba8c840a1e95b833da *inst/include/cppad/local/declare_ad.hpp 02a8e5aad9daccffcca39899b79dd1c5 *inst/include/cppad/local/define.hpp 8e41d324f9e0ed7caaf9606a42dd82cd *inst/include/cppad/local/dependent.hpp a6339e9bf1f4d33f5cab1eaf4aea4124 *inst/include/cppad/local/discrete.hpp a85b45c800d412831d738001372d7830 *inst/include/cppad/local/discrete_op.hpp 99584a30af00798e3ea75e39121a8755 *inst/include/cppad/local/div.hpp c8374d5cc22539151f53b73e7a642d66 *inst/include/cppad/local/div_eq.hpp 72233c1f5a7135ee53141a072ec18c52 *inst/include/cppad/local/div_op.hpp eca975875eea29c1b8ef8f6bcfe2f6c9 *inst/include/cppad/local/drivers.hpp 176cd862d506c585f9690f8d5125b008 *inst/include/cppad/local/epsilon.hpp fc851910d38f757106f659dec4e26568 *inst/include/cppad/local/equal_op_seq.hpp 4db246a15a8eafa2cb39443bc2a243aa *inst/include/cppad/local/erf.hpp 7d83e2e88f556909d8cd3a545beb6e79 *inst/include/cppad/local/erf_op.hpp e40c89d5f6f619934afb3684fa785efb *inst/include/cppad/local/exp_op.hpp 2fbe063f232e4c8e0cbfa543f6b120eb *inst/include/cppad/local/for_jac_sweep.hpp bf86f4c21e300818f2a86fe4cb56bd10 *inst/include/cppad/local/for_one.hpp 0ed10ffe128e9c1a40c10b6a12a5c5e8 *inst/include/cppad/local/for_sparse_jac.hpp 22366b2da11628c4738216934a78d80d *inst/include/cppad/local/for_two.hpp 52988261e60d5995bca6abf459ea0abd *inst/include/cppad/local/forward.hpp 304364d54200641c6718cf2efe8ea93d *inst/include/cppad/local/forward0sweep.hpp 4f6a829b7d443d6f960097e33974d8e1 *inst/include/cppad/local/forward1sweep.hpp bc8caef8e6aff0746c237e6f560aad22 *inst/include/cppad/local/forward2sweep.hpp f5d512374c2470d69fe2f929f6e1e0cc *inst/include/cppad/local/fun_check.hpp c92cc9ca499cc00ca4e58ec9684b5c18 *inst/include/cppad/local/fun_construct.hpp 06f54f960c97c710e0d46ee8e917ea70 *inst/include/cppad/local/fun_eval.hpp 77407c03bc58cfb90f02769132b79663 *inst/include/cppad/local/hash_code.hpp 91b1555e4bd4a8e66580e089b065f680 *inst/include/cppad/local/hessian.hpp c9b5310bb9f48a7456cdc041d59ff0f3 *inst/include/cppad/local/identical.hpp e6e7b9aedc7578b1ab267722f9a66eea *inst/include/cppad/local/independent.hpp 1ab79299fd1800d9edd749fc1d705c78 *inst/include/cppad/local/integer.hpp e0479bd04e2f5a9c7aa5d2cf1ded78f3 *inst/include/cppad/local/jacobian.hpp c1b8ea5f3320bff801367303c0914ae1 *inst/include/cppad/local/kasper.hpp 284616db995e67c7edf31ba987775bfb *inst/include/cppad/local/limits.hpp f5e1cffa1fb5bea7bb331d636265563e *inst/include/cppad/local/load_op.hpp b4130da7bbc583fa678f28d832659085 *inst/include/cppad/local/log_op.hpp 85b4eb57dd50583aba6ee7dcd942db82 *inst/include/cppad/local/lu_ratio.hpp ecef2fa272d930b83349f6874a8c76a4 *inst/include/cppad/local/math_other.hpp d92d5cabeeaacf789cb48a68318470f3 *inst/include/cppad/local/mul.hpp 1ee6d5693ef6b64b3f465fe6355a98c5 *inst/include/cppad/local/mul_eq.hpp 8c6961e38840e4575fa07ef7e7840228 *inst/include/cppad/local/mul_op.hpp ed7b9f14822bd934175b6106ab05c761 *inst/include/cppad/local/near_equal_ext.hpp 2cce792465cda30e310f3d71a3cc044f *inst/include/cppad/local/num_skip.hpp 4bae1f0e0e33d1285205c99650c8b73a *inst/include/cppad/local/old_atomic.hpp 13c422225b5fddc48352e70a6ed78b88 *inst/include/cppad/local/omp_max_thread.hpp e7151e209f184859ff318fae3d367bfd *inst/include/cppad/local/op.hpp 66e9c7d0f34e897397ab4960074f64e5 *inst/include/cppad/local/op_code.hpp 113f2fe796cc5317fb15d913cd8a1a2b *inst/include/cppad/local/opt_val_hes.hpp 71e5e0328a06564cb2229a0f12174a82 *inst/include/cppad/local/optimize.hpp 2d129dae34c7a475880068792f4a6ad0 *inst/include/cppad/local/ordered.hpp 341b2e6b6c1747631f8728f4211c1545 *inst/include/cppad/local/par_var.hpp b378cd0a66097439c0c2357f1f6e543a *inst/include/cppad/local/parallel_ad.hpp 4d8dba17a05f24c37da9d975007bdc26 *inst/include/cppad/local/parameter_op.hpp 29a5bcb0c19d7e6650bcce7c2f85d310 *inst/include/cppad/local/player.hpp 7fe1339760b2498a6b9354f3957d758e *inst/include/cppad/local/pod_vector.hpp 6ab45e1fb56b1052d9c8f125830df6bd *inst/include/cppad/local/pow.hpp bb31706c71bf5647da25ad0cd8f69b80 *inst/include/cppad/local/pow_op.hpp 09238dce0c659ff9780e3ca4b557f43f *inst/include/cppad/local/print_for.hpp 32adbc41bd2f54bd537f0da1b7a53cd7 *inst/include/cppad/local/print_op.hpp 3a5e9c965f11bc23b201ce31863951a6 *inst/include/cppad/local/prototype_op.hpp 8c2dc4650525a1cee08d5e8124d462ef *inst/include/cppad/local/recorder.hpp 6f1611076701e93832293b36edd14b64 *inst/include/cppad/local/rev_hes_sweep.hpp 042deede81928bc16dc464372c11e327 *inst/include/cppad/local/rev_jac_sweep.hpp 43118b714d743ea554a6d76f1d6dc8e8 *inst/include/cppad/local/rev_one.hpp 1adf05863d960e87bbd196e71a584eee *inst/include/cppad/local/rev_sparse_hes.hpp e5d6b5677c6c1963ea992d8c061bbe4a *inst/include/cppad/local/rev_sparse_jac.hpp 6bc82e2dc2d362c125004512eac2c0f0 *inst/include/cppad/local/rev_two.hpp 87bcf743ee22636e4560258375da75f2 *inst/include/cppad/local/reverse.hpp e6cf2edb4bb05f005ad70f2fd34602bb *inst/include/cppad/local/reverse_sweep.hpp e7c9373e5b1120b0130b21cae904c4cc *inst/include/cppad/local/sign.hpp 6d4c3a1f98b017a6f22d54bb276e7ce5 *inst/include/cppad/local/sign_op.hpp 7b1d1fe78ee4f44e77c2f3f88900ffa8 *inst/include/cppad/local/sin_op.hpp 324bcb33f11e83d922b10975ba8e533a *inst/include/cppad/local/sinh_op.hpp a26796365dd574e7ae1fb676b5b8caf0 *inst/include/cppad/local/sparse.hpp 3f1ef3459ccb2542aa8c13058df3ac7f *inst/include/cppad/local/sparse_binary_op.hpp 2f10857993b397b10504b5bdb318a89c *inst/include/cppad/local/sparse_hessian.hpp 1fab484b3732b2001a53a47eb8f7de12 *inst/include/cppad/local/sparse_jacobian.hpp ccc2397558b31950b043987c41869447 *inst/include/cppad/local/sparse_list.hpp 391c13cdee23d141c22f35874f5b4694 *inst/include/cppad/local/sparse_pack.hpp 9dde5bc4e71e383594f3ef8e2b277ec0 *inst/include/cppad/local/sparse_pattern.hpp 23b2dea1f727141958416c61a27882bd *inst/include/cppad/local/sparse_set.hpp 969faef671598b38dc25a3384783a07f *inst/include/cppad/local/sparse_unary_op.hpp 9a353eb97be219baab747d09ade344e1 *inst/include/cppad/local/sqrt_op.hpp a4f0bcd91eef71936bb272798fda88dc *inst/include/cppad/local/std_math_ad.hpp 3ad45dbba6cd7d00ae1f2d584d6e099f *inst/include/cppad/local/std_set.hpp 3fe52ac60b9d48d8cec2b7cccf0ddc4f *inst/include/cppad/local/store_op.hpp 8f44194dc81778d9202dcb6a2a4e8c24 *inst/include/cppad/local/sub.hpp eb72c8b56d5ecf4477e4abed680a415e *inst/include/cppad/local/sub_eq.hpp 0a3d9f0e77d2a98949ff46d65643e499 *inst/include/cppad/local/sub_op.hpp b2708f8bef32c00d87f04d83f493e428 *inst/include/cppad/local/tan_op.hpp 8237668f922bd7369d2584895b1c8fe5 *inst/include/cppad/local/tanh_op.hpp 150472f1cdbed489690c523a20bb0f0e *inst/include/cppad/local/tape_link.hpp 92c2f3706dd950962ffc66d9ff815b47 *inst/include/cppad/local/test_vector.hpp a171dcfed372f3bcc49f3abac7413d8a *inst/include/cppad/local/testvector.hpp e3b1058ad33e8abab3c57d7c74925503 *inst/include/cppad/local/unary_minus.hpp f8cb0595fae35df17e2a7637b60ab256 *inst/include/cppad/local/unary_plus.hpp 09af3b277558e4e14076215f202d7710 *inst/include/cppad/local/undef.hpp 533d5cff5289f7f00dd238f9d7d8e13b *inst/include/cppad/local/user_ad.hpp acc8b86c6362d5f8bc70a9bf05764157 *inst/include/cppad/local/value.hpp 348b4fd631b19db32162adcf382e12a0 *inst/include/cppad/local/var2par.hpp e8cf7335073abf5e871bc7d1368ee81c *inst/include/cppad/local/vec_ad.hpp 220b0b1c7d8bf92fd2f92cef6610093f *inst/include/cppad/lu_factor.hpp a6d79e1ec324331074a865e82f37718b *inst/include/cppad/lu_invert.hpp 762854320abacde390c79b2a9e148516 *inst/include/cppad/lu_solve.hpp 098edbc35d4fae23f2b2c6e7377c0826 *inst/include/cppad/memory_leak.hpp fe2cdee7022a4954acd05be4167344a4 *inst/include/cppad/nan.hpp 1486672de8de78fa69feb1ec3c33bd2e *inst/include/cppad/near_equal.hpp 7048ffdd93977c6b248e721ce93c2398 *inst/include/cppad/ode_err_control.hpp 3232493d20851c713d1a3f003ca19feb *inst/include/cppad/ode_gear.hpp 750a7eb9d7851e0e53f5bfefe10dab81 *inst/include/cppad/ode_gear_control.hpp bb34b7f5d995d2b63e6c67cf8826b567 *inst/include/cppad/omp_alloc.hpp 7ab3508e35cff8c47f2a65aa76dd7e09 *inst/include/cppad/poly.hpp ffdf6cd4728cabc91aaab750484a8ef1 *inst/include/cppad/pow_int.hpp 0d34303592d393571ffaf9489d03b601 *inst/include/cppad/romberg_mul.hpp 73cdf88ace1a19f1e28b592b56a7ccdd *inst/include/cppad/romberg_one.hpp 805719a78683f5fc1daf069bedbb638c *inst/include/cppad/rosen_34.hpp 271544538ce56d5b57740e39ef3ac0b1 *inst/include/cppad/runge_45.hpp 2244a061bcca4ee376f191420e4315fc *inst/include/cppad/speed/det_33.hpp aa4b016505e5e5c19a26641ffaf52990 *inst/include/cppad/speed/det_by_lu.hpp db1e7cd61a4da644509b254c4381bc30 *inst/include/cppad/speed/det_by_minor.hpp bbcc516c2cbc6cdf7923f5adbbea7616 *inst/include/cppad/speed/det_grad_33.hpp 031cbbe681eb322ac86d7f688ff817e8 *inst/include/cppad/speed/det_of_minor.hpp 98edf14ec6105d66729c4e590256c361 *inst/include/cppad/speed/mat_sum_sq.hpp ce73494269311e976a8137ed2e3043d3 *inst/include/cppad/speed/ode_evaluate.hpp d240210ad9e473480541fd8b97614be6 *inst/include/cppad/speed/sparse_hes_fun.hpp 82cb08c63266acd7e10d1263f7bed12b *inst/include/cppad/speed/sparse_jac_fun.hpp 34455739b0171ff3778fd719696068b0 *inst/include/cppad/speed/uniform_01.hpp 3a2c097c6b91a5f929bf6a4b5e0d6653 *inst/include/cppad/speed_test.hpp d69dcf21744dca401515265eb37300bb *inst/include/cppad/thread_alloc.hpp 3d363be95f48df10039e506ae4e0a3b0 *inst/include/cppad/time_test.hpp 6030d3bff0a09beefc6ed747866d1b20 *inst/include/cppad/track_new_del.hpp 8082ce868a2fb453e09a23d18a5beb3d *inst/include/cppad/vector.hpp 6e4cad3bc080c35149c2533771c7b426 *inst/include/distributions_R.hpp fb91d053ca670d87de3155c2a53149ab *inst/include/dnorm.hpp 7cb6ef0ce67d83de587c5f6b73a1e314 *inst/include/dynamic_data.hpp ac758074c7f643e2f59c55c771c70b35 *inst/include/expm.hpp 325cfa2093bb253bc680a62f23b12539 *inst/include/fft.hpp 426b135e048a69cc2486a23b943a406a *inst/include/lgamma.hpp d41d8cd98f00b204e9800998ecf8427e *inst/include/precompile.hpp ec06900458e1f836bdcdd282d36e4fff *inst/include/start_parallel.hpp b09fb12f2a0b7c8e64583af58e6614a5 *inst/include/tiny_ad/atomic.hpp 3abc7594697713ba497872af1d0151b3 *inst/include/tiny_ad/bessel/bessel.h 277b8d52540cf2a36aef0b113cabbd1f *inst/include/tiny_ad/bessel/bessel.hpp a7478f4abea9d29b00797bccf1d3fb2b *inst/include/tiny_ad/bessel/bessel_i.cpp c2f59868f147580996eec7b9c5772722 *inst/include/tiny_ad/bessel/bessel_j.cpp 40e32c410ab2613ebcbdaa488fd83bfc *inst/include/tiny_ad/bessel/bessel_k.cpp 6cd58da4f6e8cd4d6444403a0bbe92a1 *inst/include/tiny_ad/bessel/bessel_y.cpp bc43041037cf940fd58d27a01f5f99a3 *inst/include/tiny_ad/bessel/undefs.h 8cadcb150ab29a23c6744173e0852858 *inst/include/tiny_ad/beta/d1mach.cpp a1b9bc692c40cbb99ef68717f364c2dc *inst/include/tiny_ad/beta/dpq.h 1137c5808d2a3386b1c1bc323e996b45 *inst/include/tiny_ad/beta/i1mach.cpp 31b6ee7aafba5d9247a8bf7064f6f9c9 *inst/include/tiny_ad/beta/nmath.h 92209ca3053abcd475010015e737f0c8 *inst/include/tiny_ad/beta/pbeta.cpp 7aa5084cc84ff89ea16c72990f6f12f7 *inst/include/tiny_ad/beta/pbeta.hpp 13436e9bcd6f2badadcd158675f9ccc1 *inst/include/tiny_ad/beta/toms708.cpp 10bee0b4fe9c9e9add25d6c4b3a769b1 *inst/include/tiny_ad/beta/undefs.h 75bcbfba021021a2dd1ba5a7bbd7acca *inst/include/tiny_ad/compois/compois.hpp 87fb93a3b88ccb569e26ec31523e1ede *inst/include/tiny_ad/gamma/chebyshev.cpp 5414e74b84672ff1ff49d0917500e27f *inst/include/tiny_ad/gamma/gamma.cpp 7ceb076a5704a85a9bf7b3b2f60d25a9 *inst/include/tiny_ad/gamma/gamma.hpp f3b6489843704107641ce12c23ffbf90 *inst/include/tiny_ad/gamma/gamma_cody.cpp 1c7351509cc9cfd2402237a8deb3f151 *inst/include/tiny_ad/gamma/gammalims.cpp.not_used a7e97c5f9d542e34ef1260a963a4754d *inst/include/tiny_ad/gamma/lgamma.cpp e134dcdf5fa724b5c1d1dbdd03e4a910 *inst/include/tiny_ad/gamma/lgammacor.cpp 0bab865a845a214e5fd92bf4a93ffeca *inst/include/tiny_ad/gamma/stirlerr.cpp 6477636d15e69a8ffd1e9e3a209737b3 *inst/include/tiny_ad/gamma/undefs.h 8079597f39fea50c1bb5090dd3b331b8 *inst/include/tiny_ad/integrate/integrate.cpp 9319082a3bafaf97898d098d0a9a7605 *inst/include/tiny_ad/integrate/integrate.hpp ba0e5c9d4bcc8377403787e09dde1379 *inst/include/tiny_ad/mask.hpp bac55137b4e3a7a39ec2781f5357cc5c *inst/include/tiny_ad/robust/distributions.hpp 6adb743e17fbb4f52995536445a3f0d5 *inst/include/tiny_ad/tiny_ad/tiny_ad.hpp d5bd4e8231b4d9e9c908d52437e4b963 *inst/include/tiny_ad/tiny_ad/tiny_valarray.hpp bed275688206d95b0fd155d5c6b1bc96 *inst/include/tiny_ad/tiny_ad/tiny_vec.hpp 0a40a6854ee55c83099eae8c54db9831 *inst/include/tiny_ad/tweedie/tweedie.cpp 65aa74eb2b6c7aea9a23753325879929 *inst/include/tiny_ad/tweedie/tweedie.hpp 12fa51841e02861c0106af7e38371bd2 *inst/include/tmb_core.hpp a46fde809b02002b302587fc1ff337db *inst/include/tmb_enable_header_only.hpp 5ad83fb51d885eaf2583324cf8c55e5b *inst/include/tmb_enable_precompile.hpp cba5dbd26e532656b13f717613adda93 *inst/include/tmbad_atomic_macro.hpp 896864fb1ea451068388ea287479682a *inst/include/tmbutils/R_inla.hpp a033a5cedea4b808637d71b5960c859b *inst/include/tmbutils/array.hpp e859bdd25a03f386c71d3fb94a723cbc *inst/include/tmbutils/autodiff.hpp c96c599ba5f0e8bb0dd0893a367851fe *inst/include/tmbutils/concat.hpp c7bb7424b1db4fbde76a1945629336a9 *inst/include/tmbutils/density.hpp 855d87b2e8f248a114f08f7e2ed8f65a *inst/include/tmbutils/getListElement.hpp 8d67ef0679cfb44547e221feabbacb1f *inst/include/tmbutils/interpol.hpp 7ec47588c1dcad646f724f9b6dc07810 *inst/include/tmbutils/kronecker.hpp a5d52f1782b16620d8bbcd7dff948f52 *inst/include/tmbutils/matexp.hpp 7f5a12ab4ab3efd827aab62579999fcd *inst/include/tmbutils/newton.hpp 4bae9e452a2191da9bbd9e88cb133bf7 *inst/include/tmbutils/order.hpp ff02e0a781e0e5b9023229f8c1d9019b *inst/include/tmbutils/romberg.hpp 74165a766bb2d9fa7a2cc09fdbf7698e *inst/include/tmbutils/simplicial_inverse_subset.hpp fb54588710dc7f24a529cb7f2d935e25 *inst/include/tmbutils/sparse_matrix_exponential.hpp 820d43d49b901be4db059ee51e284a10 *inst/include/tmbutils/splines.hpp 3e607b30aa2b69d50a481d37f10cf5c1 *inst/include/tmbutils/spmat.hpp 5dd9f4493291044e64998b2ac61daf84 *inst/include/tmbutils/supernodal_inverse_subset.hpp e7be1be77ff4c334771b462114d6b52c *inst/include/tmbutils/tmbutils.hpp 47fffe15f21dde554416ea62818d8787 *inst/include/tmbutils/tmbutils_extra.hpp 234f0579fd7f4950be20a74c9ec69095 *inst/include/tmbutils/vector.hpp 1fd33ea45585479c27b20327ac2256f9 *inst/include/tmbutils/vectorize.hpp 852feac7e8101790d3de80c6f0371db5 *inst/include/toggle_thread_safe_R.hpp cac34e6a00e1d301fadd4c4e5f4744d3 *inst/template.cpp 585ff35e0e23841ed42e02e7a8d97d36 *man/FreeADFun.Rd fdbfdb249fd6f51b839f9f7aca5b86d1 *man/GK.Rd 5e05db54772d2e5a889ed7d96299ccbc *man/MakeADFun.Rd c1890fbd90543617a3dd7a37c7a111d8 *man/Rinterface.Rd f3cb41bb8a69add2ac41ef4130e288fe *man/SR.Rd 34a86ce50c73b59cc4bdb30169058536 *man/as.list.sdreport.Rd dba8487666ca309829273c6fda29ee86 *man/benchmark.Rd b3c3979d28fd2edeb9dd87cf5a56b8a7 *man/checkConsistency.Rd 443dff9ba715efff6085906c21a5df1e *man/compile.Rd e2ebe83f3d55f97fb97da7eba5481971 *man/config.Rd d6ae8026f7cbf442e7ef8cf7e4485913 *man/confint.tmbprofile.Rd ff112270c193b9e4a32bb2d8f81e1482 *man/dynlib.Rd bb279403622341fa8afdaff4020ea725 *man/gdbsource.Rd 2959d71fedaf6d61053a6af4b966fc4b *man/newton.Rd 2df5d692b73bc2abbdcef7aa31f2592a *man/newtonOption.Rd 5d42b2ff227a31661ae04fcddd2ad9b2 *man/normalize.Rd f80a1a2c1a57d7e157479d5e22fcc77b *man/oneStepPredict.Rd 4314d6fc66468b5dd45cd2b78a7dd7ad *man/openmp.Rd c724052dd366049d54bdbdd8e23b12a4 *man/plot.tmbprofile.Rd 953aeade34f36c16824a8318f494c7f2 *man/precompile.Rd 25ad4fde0a0b80fd88653f38fe0deadb *man/print.checkConsistency.Rd 3b5b5c89804a350f22a8633960d1a344 *man/print.sdreport.Rd d0fee90577a57ef202a879aed448911e *man/runExample.Rd bb9feb042c215118410ac6b97c2d245a *man/runSymbolicAnalysis.Rd 80399c6f7f069962f9bde3d63e0966bf *man/sdreport.Rd 06b97be5fa5240be0811e120593fbd7f *man/summary.checkConsistency.Rd d8a0d3277078f18136a86ebc15ff49b4 *man/summary.sdreport.Rd 9dd84471758f8d925c18d3744d72e71e *man/template.Rd 25ab1a0b79b4356fefa8780771d031f4 *man/tmbprofile.Rd 360c1a036606f6f1315e478a8e5559ab *man/tmbroot.Rd c29b28480a5bee583f9900da5d0adbbf *src/Makevars 9d60805278b72ef9f60edb396b85b77d *src/external_metis.c 412ff0f60a76105f734d3ac9445dd1cf *src/init.c befc9fe6d7fd47dbd1e1964357f17a0b *src/local_stubs.c b6a55024c034730e142d68650b913927 *src/solve_subset.c 49030ef72eb1395af7c71a40d1d256d9 *src/utils.c TMB/inst/0000755000176200001440000000000014113627761011661 5ustar liggesusersTMB/inst/examples/0000755000176200001440000000000014527235235013477 5ustar liggesusersTMB/inst/examples/linreg_parallel.R0000644000176200001440000000047314527235235016762 0ustar liggesuserslibrary(TMB) dyn.load(dynlib("linreg_parallel")) ## Simulate data set.seed(123) x <- seq(0, 10, length.out = 50001) data <- list(Y = rnorm(length(x)) + x, x = x) parameters <- list(a=0, b=0, logSigma=0) ## Fit model obj <- MakeADFun(data, parameters, DLL="linreg_parallel") opt <- nlminb(obj$par, obj$fn, obj$gr) TMB/inst/examples/simple.R0000644000176200001440000000142714276702134015115 0ustar liggesusersrequire(TMB) dyn.load(dynlib("simple")) ## Test data set.seed(123) y <- rep(1900:2010,each=2) year <- factor(y) quarter <- factor(rep(1:4,length.out=length(year))) period <- factor((y > mean(y))+1) ## Random year+quarter effect, fixed period effect: B <- model.matrix(~year+quarter-1) A <- model.matrix(~period-1) B <- as(B,"TsparseMatrix") A <- as(A,"TsparseMatrix") u <- rnorm(ncol(B)) ## logsdu=0 beta <- rnorm(ncol(A))*100 eps <- rnorm(nrow(B),sd=1) ## logsd0=0 x <- as.numeric( A %*% beta + B %*% u + eps ) ## Fit model obj <- MakeADFun(data=list(x=x, B=B, A=A), parameters=list(u=u*0, beta=beta*0, logsdu=1, logsd0=1), random="u", DLL="simple", silent=TRUE ) opt <- nlminb(obj$par, obj$fn, obj$gr) TMB/inst/examples/ar1xar1.R0000644000176200001440000000257714113627760015113 0ustar liggesusersrequire(TMB) set.seed(123) n <- 50 ## Size of problem = n*n ## ======================= Simulate separable 2D GMRF ## - With exponential correlation in both directions ## - phi1 = 1-lag correlation in 1st direction ## - phi2 = 1-lag correlation in 2nd direction ar1corr <- function(n,phi){ phi^abs(outer(1:n,1:n,"-")) } simgmrf <- function(n1,n2,phi1,phi2){ u <- matrix(rnorm(n1*n2),n1,n2) L1 <- t(chol(ar1corr(n1,phi1))) L2 <- t(chol(ar1corr(n2,phi2))) x <- L1%*%u ## phi1 in 1st direction (fastest) x <- t(L2%*%t(x)) ## phi2 in 2nd direction x } ## ======================= Simulate data phi1=exp(-1/(.1*n)) ## Correlation range=10% of grid size first dimension phi2=exp(-1/(.2*n)) ## Correlation range=20% of grid size second dimension eta <- simgmrf(n,n,phi1,phi2) N <- rpois(length(eta),exp(eta)) d <- expand.grid(x=factor(1:n),y=factor(1:n)) d$N <- N ## ======================= Parameterization of phi f <- function(x) 2/(1 + exp(-2 * x)) - 1 invf <- function(y) -0.5 * log(2/(y + 1) - 1) ## ======================= Fit model dyn.load(dynlib("ar1xar1")) obj <- MakeADFun(data=list(N=N), parameters=list( eta=matrix(0,n,n), transf_phi1=invf(0.5), transf_phi2=invf(0.5)), random=c("eta"), DLL="ar1xar1") runSymbolicAnalysis(obj) opt <- nlminb(obj$par, obj$fn, obj$gr) TMB/inst/examples/randomregression.cpp0000644000176200001440000000164114113627760017565 0ustar liggesusers// Regression model with random slope and intercept. #include template Type objective_function::operator() () { DATA_FACTOR(group); DATA_VECTOR(x); DATA_VECTOR(t); PARAMETER_VECTOR(a); // Slope for given individual PARAMETER_VECTOR(b); // Intercept for given individual PARAMETER_VECTOR(mu); // length 2 - one for slope, one for intercept PARAMETER_VECTOR(sigma); // length 2 - one for slope, one for intercept PARAMETER(sigma0); int nobs = x.size(); int ngroups = a.size(); Type res = 0; int j; /* Prior: slope ~ N(mu0,sd0), intercept ~ N(mu1,sd1) */ for(int j=0; j < ngroups; j++){ res -= dnorm(a[j], mu[0], sigma[0], true); res -= dnorm(b[j], mu[1], sigma[1], true); } /* Observations: x|a,b ~ N(a*t+b,sigma0) */ for(int i = 0; i < nobs; i++){ j = group[i]; res -= dnorm(x[i], a[j] * t[i] + b[j], sigma0, true); } return res; } TMB/inst/examples/simple.cpp0000644000176200001440000000227714113627760015503 0ustar liggesusers// Normal linear mixed model specified through sparse design matrices. #include template Type objective_function::operator() () { DATA_VECTOR(x); // Observations DATA_SPARSE_MATRIX(B); // Random effect design matrix DATA_SPARSE_MATRIX(A); // Fixed effect design matrix PARAMETER_VECTOR(u); // Random effects vector PARAMETER_VECTOR(beta); // Fixed effects vector PARAMETER(logsdu); // Random effect standard deviations PARAMETER(logsd0); // Measurement standard deviation // Distribution of random effect (u): Type ans = 0; ans -= dnorm(u, Type(0), exp(logsdu), true).sum(); // Optionally: How to simulate the random effects SIMULATE { u = rnorm(u.size(), Type(0), exp(logsdu)); REPORT(u); } // Distribution of obs given random effects (x|u): vector y = A * beta + B * u; ans -= dnorm(x, y, exp(logsd0), true).sum(); // Optionally: How to simulate the data SIMULATE { x = rnorm(y, exp(logsd0)); REPORT(x); } // Apply delta method on sd0: Type sd0=exp(logsd0); ADREPORT( sd0 ); REPORT(sd0); // Report posterior mode and mean of sum(exp(u)) ADREPORT( sum(exp(u)) ); return ans; } TMB/inst/examples/randomregression.R0000644000176200001440000000162214113627760017203 0ustar liggesusersrequire(TMB) dyn.load(dynlib("randomregression")) ## Simulate random regression set.seed(123) n <- 100 ng <- 10 f <- gl(ng, n/ng) t <- rnorm(n, mean=2, sd=5) a <- rnorm(ng, mean=3, sd=4) b <- rnorm(ng, mean=8, sd=7) x <- a[f] * t + b[f] + rnorm(n, mean=0, sd=1) if(FALSE){ library(lattice); xyplot(x ~ t, group = f, type="l") } ## Construct AD function object data <- list(group=f, x=x, t=t) parameters <- list( a = rep(1, nlevels(f)), b = rep(1, nlevels(f)), mu = rep(1, 2), sigma = rep(1, 2), sigma0 = 1 ) obj <- MakeADFun(data = data, parameters = parameters, random = c("a", "b"), DLL = "randomregression" ) ## Test eval function and gradient obj$fn() obj$gr() ## Fit model opt <- nlminb(obj$par, obj$fn, obj$gr) opt$par TMB/inst/examples/ar1xar1.cpp0000644000176200001440000000171514113627760015465 0ustar liggesusers// Separable covariance on lattice with AR1 structure in each direction. #include /* Parameter transform */ template Type f(Type x){return Type(2)/(Type(1) + exp(-Type(2) * x)) - Type(1);} template Type objective_function::operator() () { DATA_VECTOR(N) PARAMETER_ARRAY(eta); PARAMETER(transf_phi1); /* fastest running dim */ PARAMETER(transf_phi2); /* slowest running dim */ Type phi1 = f(transf_phi1); Type phi2 = f(transf_phi2); using namespace density; Type res = 0; res += SEPARABLE( AR1(phi2), AR1(phi1) )(eta); /* keep = vector of ones */ DATA_VECTOR_INDICATOR(keep, N); for(int i=0; i < N.size(); i++){ res -= keep[i] * dpois(N[i], exp(eta[i]), true); /* For OSA residuals only: */ Type cdf = squeeze( ppois(N[i], exp(eta[i])) ); res -= keep.cdf_lower[i] * log( cdf ); // NaN protected res -= keep.cdf_upper[i] * log( 1.0 - cdf ); // NaN protected } return res; } TMB/inst/examples/linreg_parallel.cpp0000644000176200001440000000055614113627760017344 0ustar liggesusers// Linear regression model in parallel. #include template Type objective_function::operator() () { DATA_VECTOR(Y); DATA_VECTOR(x); PARAMETER(a); PARAMETER(b); PARAMETER(logSigma); parallel_accumulator nll(this); for(int i=0; i However, Rmath defines a large number of macros that do not respect the namespace limits. Some of them will conflict with other TMB functions or mess up symbols in the users template (e.g. change 'dt' to 'Rf_dt'). Therefore, explicitly select the few function headers (from /usr/share/R/include/Rmath.h) rather than including them all. */ extern "C" { /* See 'R-API: entry points to C-code' (Writing R-extensions) */ double Rf_pnorm5(double, double, double, int, int); double Rf_qnorm5(double, double, double, int, int); double Rf_ppois(double, double, int, int); double Rf_bessel_k(double, double, double); double Rf_bessel_i(double, double, double); double Rf_pgamma(double, double, double, int, int); double Rf_qgamma(double, double, double, int, int); double Rf_lgammafn(double); double Rf_psigamma(double, double); double Rf_fmin2(double, double); /* Selected headers from */ typedef void integr_fn(double *x, int n, void *ex); void Rdqags(integr_fn f, void *ex, double *a, double *b, double *epsabs, double *epsrel, double *result, double *abserr, int *neval, int *ier, int *limit, int *lenw, int *last, int *iwork, double *work); void Rdqagi(integr_fn f, void *ex, double *bound, int *inf, double *epsabs, double *epsrel, double *result, double *abserr, int *neval, int *ier, int *limit, int *lenw, int *last, int *iwork, double *work); } /* Non-standard TMB special functions based on numerical integration: */ #ifdef WITH_LIBTMB void integrand_D_incpl_gamma_shape(double *x, int nx, void *ex); double D_incpl_gamma_shape(double x, double shape, double n, double logc); double inv_incpl_gamma(double y, double shape, double logc); double D_lgamma(double x, double n); #else void integrand_D_incpl_gamma_shape(double *x, int nx, void *ex){ double* parms=(double*)ex; double shape = parms[0]; double n = parms[1]; double logc = parms[2]; for(int i=0; ishape){ ier = 0; double a = bound; double b = log(x); Rdqags(integrand_D_incpl_gamma_shape, ex, &a, &b, &epsabs, &epsrel, &result2, &abserr, &neval, &ier, &limit, &lenw, &last, iwork, work); if(ier!=0){ #ifndef _OPENMP Rf_warning("incpl_gamma (def) integrate unreliable: x=%f shape=%f n=%f ier=%i", x, shape, n, ier); #endif } } free(iwork); free(work); return result1 + result2; } double inv_incpl_gamma(double y, double shape, double logc){ double logp = log(y) - Rf_lgammafn(shape) - logc; double scale = 1.0; return Rf_qgamma(exp(logp), shape, scale, 1, 0); } /* n'th order derivative of log gamma function */ double D_lgamma(double x, double n){ if(n<.5)return Rf_lgammafn(x); else return Rf_psigamma(x,n-1.0); } #endif // #ifdef WITH_LIBTMB } #ifdef CPPAD_FRAMEWORK #include "atomic_macro.hpp" #endif #ifdef TMBAD_FRAMEWORK #include "tmbad_atomic_macro.hpp" #endif template struct TypeDefs{ /* The following typedefs allow us to construct matrices based on already allocated memory (pointers). 'MapMatrix' gives write access to the pointers while 'ConstMapMatrix' is read-only. */ typedef Eigen::Map > MapMatrix; typedef Eigen::Map > ConstMapMatrix; typedef Eigen::LDLT > LDLT; }; /** \internal \brief Convert segment of CppAD::vector to Eigen::Matrix \param x Input vector. \param m Number of rows in result. \param n Number of columns in result. \param offset Segment offset. */ template typename TypeDefs::ConstMapMatrix vec2mat(const CppAD::vector &x, int m, int n, int offset=0){ typedef typename TypeDefs::ConstMapMatrix ConstMapMatrix_t; ConstMapMatrix_t res(&x[offset], m, n); return res; } /** \internal \brief Convert Eigen::Matrix to CppAD::vector by stacking the matrix columns. \param x Input matrix. */ template CppAD::vector mat2vec(matrix x){ int n=x.size(); CppAD::vector res(n); for(int i=0;i Type dnorm1(Type x){ return Type(1.0/sqrt(2.0*M_PI)) * exp(-Type(.5)*x*x); } /** \brief Atomic version of standard normal distribution function. Derivative is known to be 'dnorm1'. \param x Input vector of length 1. \return Vector of length 1. */ TMB_ATOMIC_STATIC_FUNCTION( // ATOMIC_NAME pnorm1 , // INPUT_DIM 1 , // ATOMIC_DOUBLE ty[0] = Rmath::Rf_pnorm5(tx[0],0,1,1,0); , // ATOMIC_REVERSE px[0] = dnorm1(tx[0]) * py[0]; ) /** \brief Atomic version of standard normal quantile function. Derivative is expressed through 'dnorm1'. \param x Input vector of length 1. \return Vector of length 1. */ TMB_ATOMIC_STATIC_FUNCTION( // ATOMIC_NAME qnorm1 , // INPUT_DIM 1, // ATOMIC_DOUBLE ty[0] = Rmath::Rf_qnorm5(tx[0],0,1,1,0); , // ATOMIC_REVERSE px[0] = Type(1) / dnorm1(ty[0]) * py[0]; ) /** \brief Atomic version of scaled incomplete gamma function differentiated to any order wrt. shape parameter \f[ \exp(c) \int_0^{y} \exp(-t) t^{\lambda-1} \log(t)^n \:dt \f] where the 4 input parameters are passed as a vector \f$x=(y,\lambda,n,c)\f$. Note that the normalized incomplete gamma function is obtained as the special case \f$n=0\f$ and \f$c=-\log \Gamma(\lambda)\f$. Valid parameter range: \f$x \in \mathbb{R}_+\times\mathbb{R}_+\times\mathbb{N}_0\times\mathbb{R}\f$. \warning No check is performed on parameters \param x Input vector of length 4. \return Vector of length 1. */ TMB_ATOMIC_STATIC_FUNCTION( // ATOMIC_NAME D_incpl_gamma_shape , // INPUT_DIM 4 , // ATOMIC_DOUBLE ty[0]=Rmath::D_incpl_gamma_shape(tx[0],tx[1],tx[2],tx[3]); , // ATOMIC_REVERSE px[0] = exp( -tx[0] + (tx[1]-Type(1.0)) * log(tx[0]) + tx[3] ) * pow(log(tx[0]),tx[2]) * py[0]; Type tx_[4]; tx_[0] = tx[0]; tx_[1] = tx[1]; tx_[2] = tx[2] + Type(1.0); // Add one to get partial wrt. tx[1] tx_[3] = tx[3]; px[1] = D_incpl_gamma_shape(tx_) * py[0]; px[2] = Type(0); px[3] = ty[0] * py[0]; ) /** \brief Atomic version of inverse of scaled incomplete gamma function. Given \f$z\f$ find \f$y\f$ such that \f[ z = \exp(c) \int_0^{y} \exp(-t) t^{\lambda-1} \:dt \f] where the 3 input parameters are passed as a vector \f$x=(z,\lambda,c)\f$. The special case \f$c=-\log \Gamma(\lambda)\f$ gives the inverse normalized incomplete gamma function. Valid parameter range: \f$x \in \mathbb{R}_+\times\mathbb{R}_+\times\mathbb{R}\f$. \warning No check is performed on parameters \param x Input vector of length 3. \return Vector of length 1. */ TMB_ATOMIC_STATIC_FUNCTION( // ATOMIC_NAME inv_incpl_gamma , // INPUT_DIM 3 , // ATOMIC_DOUBLE ty[0]=Rmath::inv_incpl_gamma(tx[0],tx[1],tx[2]); , // ATOMIC_REVERSE Type value = ty[0]; Type shape = tx[1]; Type logc = tx[2]; Type tmp = exp(-value+logc)*pow(value,shape-Type(1)); px[0] = 1.0 / tmp * py[0]; Type arg[4]; arg[0] = value; arg[1] = shape; arg[2] = Type(1); // 1st order partial wrt. shape arg[3] = logc; px[1] = -D_incpl_gamma_shape(arg) / tmp * py[0]; arg[2] = Type(0); // 0 order partial wrt. shape px[2] = -D_incpl_gamma_shape(arg) / tmp * py[0]; ) /** \brief Atomic version of the n'th order derivative of the log gamma function. \f[ \frac{d^n}{d\lambda^n}\log \Gamma(\lambda) \f] where the 2 input parameters are passed as a vector \f$x=(\lambda,n)\f$. The special case \f$n=0\f$ gives the log gamma function. \param x Input vector of length 2. \return Vector of length 1. */ TMB_ATOMIC_STATIC_FUNCTION( // ATOMIC_NAME D_lgamma , // INPUT_DIM 2 , // ATOMIC_DOUBLE ty[0]=Rmath::D_lgamma(tx[0],tx[1]); , // ATOMIC_REVERSE Type tx_[2]; tx_[0]=tx[0]; tx_[1]=tx[1]+Type(1.0); px[0] = D_lgamma(tx_) * py[0]; px[1] = Type(0); ) /** \brief Atomic version of poisson cdf \f$ppois(n,\lambda)\f$. Valid parameter range: \f$x =(n,\lambda) \in \mathbb{N}_0\times\mathbb{R}_+\f$. \warning No check is performed on parameters \param x Input vector of length 2. \return Vector of length 1. */ TMB_ATOMIC_STATIC_FUNCTION( // ATOMIC_NAME ppois , // INPUT_DIM 2 , // ATOMIC_DOUBLE ty[0]=Rmath::Rf_ppois(tx[0],tx[1],1,0); , // ATOMIC_REVERSE Type value = ty[0]; Type n = tx[0]; Type lambda = tx[1]; Type arg[2]; arg[0] = n - Type(1); arg[1] = lambda; px[0] = Type(0); px[1] = (-value + ppois(arg)) * py[0]; ) /** \brief Atomic version of \f$besselK(x,\nu)\f$. Valid parameter range: \f$x =(x,\nu) \in \mathbb{R}_+\times\mathbb{R}\f$. \note This atomic function does not handle the derivative wrt. \f$\nu\f$. \param x Input vector of length 2. \return Vector of length 1. */ TMB_ATOMIC_STATIC_FUNCTION( // ATOMIC_NAME bessel_k_10 , // INPUT_DIM 2 , // ATOMIC_DOUBLE ty[0] = Rmath::Rf_bessel_k(tx[0], tx[1], 1.0 /* Not scaled */); , // ATOMIC_REVERSE Type value = ty[0]; Type x = tx[0]; Type nu = tx[1]; Type arg[2]; arg[0] = x; arg[1] = nu + Type(1); px[0] = ( -bessel_k_10(arg) + value * (nu / x) ) * py[0]; px[1] = Type(0); /* Not implemented (!) */ ) /** \brief Atomic version of \f$besselI(x,\nu)\f$. Valid parameter range: \f$x =(x,\nu) \in \mathbb{R}_+\times\mathbb{R}\f$. \note This atomic function does not handle the derivative wrt. \f$\nu\f$. \param x Input vector of length 2. \return Vector of length 1. */ TMB_ATOMIC_STATIC_FUNCTION( // ATOMIC_NAME bessel_i_10 , // INPUT_DIM 2 , // ATOMIC_DOUBLE ty[0] = Rmath::Rf_bessel_i(tx[0], tx[1], 1.0 /* Not scaled */); , // ATOMIC_REVERSE Type x = tx[0]; Type nu = tx[1]; Type arg[2]; arg[0] = x; arg[1] = nu + Type(1); Type B_right = bessel_i_10(arg); arg[1] = nu - Type(1); Type B_left = bessel_i_10(arg); px[0] = Type(0.5) * ( B_left + B_right ) * py[0]; px[1] = Type(0); /* Not implemented (!) */ ) /** \cond */ template /* Header of matmul interface */ matrix matmul(matrix x, matrix y); template<> matrix matmul(matrix x, matrix y)CSKIP({ return x*y; }) /** \endcond */ /** \brief Atomic version of matrix multiply. Multiplies n1-by-n2 matrix with n2-by-n3 matrix. \param x Input vector of length 2+n1*n2+n2*n3 containing the output dimension (length=2), the first matrix (length=n1*n2) and the second matrix (length=n2*n3). \return Vector of length n1*n3 containing result of matrix multiplication. */ TMB_ATOMIC_VECTOR_FUNCTION( // ATOMIC_NAME matmul , // OUTPUT_DIM CppAD::Integer(tx[0]) * CppAD::Integer(tx[1]) , // ATOMIC_DOUBLE typedef TypeDefs::MapMatrix MapMatrix_t; typedef TypeDefs::ConstMapMatrix ConstMapMatrix_t; int n1 = CppAD::Integer(tx[0]); int n3 = CppAD::Integer(tx[1]); int n2 = ( n1 + n3 > 0 ? (tx.size() - 2) / (n1 + n3) : 0 ); ConstMapMatrix_t X(&tx[2 ], n1, n2); ConstMapMatrix_t Y(&tx[2+n1*n2], n2, n3); MapMatrix_t Z(&ty[0 ], n1, n3); Z = X * Y; , // ATOMIC_REVERSE (W*Y^T, X^T*W) typedef typename TypeDefs::MapMatrix MapMatrix_t; int n1 = CppAD::Integer(tx[0]); int n3 = CppAD::Integer(tx[1]); int n2 = ( n1 + n3 > 0 ? (tx.size() - 2) / (n1 + n3) : 0 ); matrix Xt = vec2mat(tx, n1, n2, 2).transpose(); matrix Yt = vec2mat(tx, n2, n3, 2 + n1*n2).transpose(); matrix W = vec2mat(py, n1, n3); MapMatrix_t res1(&px[2 ], n1, n2); MapMatrix_t res2(&px[2+n1*n2], n2, n3); res1 = matmul(W, Yt); // W*Y^T res2 = matmul(Xt, W); // X^T*W px[0] = 0; px[1] = 0; ) /** \brief Atomic version of matrix inversion. Inverts n-by-n matrix by LU-decomposition. \param x Input vector of length n*n. \return Vector of length n*n. */ TMB_ATOMIC_VECTOR_FUNCTION( // ATOMIC_NAME matinv , // OUTPUT_DIM tx.size() , // ATOMIC_DOUBLE typedef TypeDefs::MapMatrix MapMatrix_t; typedef TypeDefs::ConstMapMatrix ConstMapMatrix_t; int n = sqrt((double)tx.size()); ConstMapMatrix_t X(&tx[0], n, n); MapMatrix_t Y(&ty[0], n, n); Y = X.inverse(); // Use Eigen matrix inverse (LU) , // ATOMIC_REVERSE (-f(X)^T*W*f(X)^T) typedef typename TypeDefs::MapMatrix MapMatrix_t; int n = sqrt((double)ty.size()); MapMatrix_t res(&px[0], n, n); matrix W = vec2mat(py, n, n); // Range direction matrix Y = vec2mat(ty, n, n); // f(X) matrix Yt = Y.transpose(); // f(X)^T matrix tmp = matmul(W, Yt); // W*f(X)^T res = -matmul(Yt, tmp); // -f(X)^T*W*f(X)^T ) /** \brief Atomic version of log determinant of positive definite n-by-n matrix. \param x Input vector of length n*n. \return Vector of length 1. */ TMB_ATOMIC_VECTOR_FUNCTION( // ATOMIC_NAME logdet , // OUTPUT_DIM 1 , // ATOMIC_DOUBLE int n=sqrt((double)tx.size()); matrix X=vec2mat(tx,n,n); matrix LU=X.lu().matrixLU(); // Use Eigen LU decomposition vector LUdiag = LU.diagonal(); double res=LUdiag.abs().log().sum(); // TODO: currently PD only - take care of sign. ty[0] = res; , // ATOMIC_REVERSE (X^-1*W[0]) CppAD::vector invX = matinv(tx); for(size_t i=0; i::LDLT LDLT_t; using namespace Eigen; int n=sqrt((double)tx.size()); matrix X=vec2mat(tx,n,n); matrix I(X.rows(),X.cols()); I.setIdentity(); LDLT_t ldlt(X); matrix iX = ldlt.solve(I); vector D = ldlt.vectorD(); double logdetX = D.log().sum(); ty[0] = logdetX; for(int i=0;i W2=vec2mat(py,n,n,1); // Range direction matrix Y=vec2mat(ty,n,n,1); // f2(X) matrix Yt=Y.transpose(); // f2(X)^T matrix tmp=matmul(W2,Yt); // W2*f2(X)^T matrix res=-matmul(Yt,tmp); // -f2(X)^T*W2*f2(X)^T res = res + Y*W1; px=mat2vec(res); ) /* ================================== INTERFACES */ /** \brief Matrix multiply Matrix multiplication of large dense matrices. \code matrix x; matrix y; atomic::matmul(x, y); \endcode For small matrices use \code x * y; \endcode \ingroup matrix_functions */ template matrix matmul(matrix x, matrix y){ CppAD::vector arg(2+x.size()+y.size()); arg[0] = x.rows(); arg[1] = y.cols(); for(int i=0;i res(x.rows()*y.cols()); matmul(arg,res); return vec2mat(res,x.rows(),y.cols()); } /** \brief Matrix inverse Invert a matrix by LU-decomposition. \code matrix x; atomic::matinv(x); \endcode For small matrices use \code x.inverse(); \endcode \ingroup matrix_functions */ template matrix matinv(matrix x){ int n=x.rows(); return vec2mat(matinv(mat2vec(x)),n,n); } /** \brief Matrix inverse and determinant Calculate matrix inverse *and* log-determinant of a positive definite matrix. \ingroup matrix_functions */ template matrix matinvpd(matrix x, Type &logdet){ int n=x.rows(); CppAD::vector res = invpd(mat2vec(x)); logdet = res[0]; return vec2mat(res,n,n,1); } /** \brief Log-determinant of positive definite matrix \ingroup matrix_functions */ template Type logdet(matrix x){ return logdet(mat2vec(x))[0]; } /* Temporary test of dmvnorm implementation based on atomic symbols. Should reduce tape size from O(n^3) to O(n^2). */ template Type nldmvnorm(vector x, matrix Sigma){ matrix Q=matinv(Sigma); Type logdetQ = -logdet(Sigma); Type quadform = (x*(Q*x)).sum(); return -Type(.5)*logdetQ + Type(.5)*quadform + x.size()*Type(log(sqrt(2.0*M_PI))); } } /* End namespace atomic */ #include "checkpoint_macro.hpp" TMB/inst/include/atomic_macro.hpp0000644000176200001440000002331414536067013016452 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /* Flag to detect if any atomic functions have been created */ TMB_EXTERN bool atomicFunctionGenerated CSKIP(= false;) /** \brief Construct atomic vector function based on known derivatives */ #define TMB_ATOMIC_VECTOR_FUNCTION(ATOMIC_NAME, OUTPUT_DIM, ATOMIC_DOUBLE, \ ATOMIC_REVERSE) \ \ template \ void ATOMIC_NAME(const CppAD::vector& tx, \ CppAD::vector& ty) CSKIP_ATOMIC({ \ ATOMIC_DOUBLE; \ }) \ template \ CppAD::vector \ ATOMIC_NAME(const CppAD::vector& tx) CSKIP_ATOMIC({ \ CppAD::vector ty(OUTPUT_DIM); \ ATOMIC_NAME(tx, ty); \ return ty; \ }) \ IF_TMB_PRECOMPILE_ATOMICS( \ template \ void ATOMIC_NAME(const CppAD::vector& tx, \ CppAD::vector& ty); \ template \ CppAD::vector ATOMIC_NAME(const CppAD::vector& tx); \ ) \ template \ void ATOMIC_NAME(const CppAD::vector >& tx, \ CppAD::vector >& ty); \ template \ CppAD::vector > ATOMIC_NAME(const CppAD::vector >& tx); \ template \ class atomic##ATOMIC_NAME : public CppAD::atomic_base { \ public: \ atomic##ATOMIC_NAME(const char* name) : CppAD::atomic_base(name) { \ atomic::atomicFunctionGenerated = true; \ if (config.trace.atomic) \ Rcout << "Constructing atomic " << #ATOMIC_NAME << "\n"; \ this->option(CppAD::atomic_base::bool_sparsity_enum); \ } \ \ private: \ virtual bool forward(size_t p, size_t q, const CppAD::vector& vx, \ CppAD::vector& vy, \ const CppAD::vector& tx, \ CppAD::vector& ty) { \ if (q > 0) \ Rf_error("Atomic '" #ATOMIC_NAME "' order not implemented.\n"); \ if (vx.size() > 0) { \ bool anyvx = false; \ for (size_t i = 0; i < vx.size(); i++) anyvx |= vx[i]; \ for (size_t i = 0; i < vy.size(); i++) vy[i] = anyvx; \ } \ ATOMIC_NAME(tx, ty); \ return true; \ } \ virtual bool reverse(size_t q, const CppAD::vector& tx, \ const CppAD::vector& ty, \ CppAD::vector& px, \ const CppAD::vector& py) { \ if (q > 0) \ Rf_error("Atomic '" #ATOMIC_NAME "' order not implemented.\n"); \ ATOMIC_REVERSE; \ return true; \ } \ virtual bool rev_sparse_jac(size_t q, const CppAD::vector& rt, \ CppAD::vector& st) { \ bool anyrt = false; \ for (size_t i = 0; i < rt.size(); i++) anyrt |= rt[i]; \ for (size_t i = 0; i < st.size(); i++) st[i] = anyrt; \ return true; \ } \ virtual bool rev_sparse_jac(size_t q, \ const CppAD::vector >& rt, \ CppAD::vector >& st) { \ Rf_error("Should not be called"); \ } \ }; \ template \ void ATOMIC_NAME(const CppAD::vector >& tx, \ CppAD::vector >& ty) { \ static atomic##ATOMIC_NAME afun##ATOMIC_NAME( \ "atomic_" #ATOMIC_NAME); \ afun##ATOMIC_NAME(tx, ty); \ } \ template \ CppAD::vector > ATOMIC_NAME(const CppAD::vector >& tx) { \ CppAD::vector > ty(OUTPUT_DIM); \ ATOMIC_NAME(tx, ty); \ return ty; \ } #define TMB_ATOMIC_STATIC_FUNCTION( \ ATOMIC_NAME, \ INPUT_SIZE, \ ATOMIC_DOUBLE, \ ATOMIC_REVERSE \ ) \ template \ double ATOMIC_NAME (const double *tx) { \ double ty[1]; \ ATOMIC_DOUBLE; \ return ty[0]; \ } \ template \ CppAD::vector > ATOMIC_NAME(const CppAD::vector >& tx);\ template \ Type ATOMIC_NAME (const Type *tx) { \ CppAD::vector tx_(INPUT_SIZE); \ for (size_t i=0; i \ CppAD::vector > ATOMIC_NAME(const CppAD::vector > &x); \ template \ CppAD::vector ATOMIC_NAME(const CppAD::vector &x); // Helper to forward define atomic #define TMB_ATOMIC_VECTOR_FUNCTION_DEFINE(ATOMIC_NAME, \ OUTPUT_DIM, \ ATOMIC_DOUBLE, \ ATOMIC_REVERSE) \ TMB_ATOMIC_VECTOR_FUNCTION(ATOMIC_NAME, \ OUTPUT_DIM, \ ATOMIC_DOUBLE, \ ATOMIC_REVERSE) TMB/inst/include/Rstream.hpp0000644000176200001440000000354514536067013015436 0ustar liggesusers/* Borrowed from Rcpp package. Copyright (C) 2011 - 2013 Dirk Eddelbuettel, Romain Francois and Jelmer Ypma License: GPL-2 After including this file we can replace "std::cout" by "Rcout", and it will be possible to correctly capture the text output from R. */ #include #include #include template class Rstreambuf : public std::streambuf { public: Rstreambuf(){} protected: virtual std::streamsize xsputn(const char *s, std::streamsize n ); virtual int overflow(int c = EOF ); virtual int sync(); }; template class Rostream : public std::ostream { typedef Rstreambuf Buffer ; Buffer* buf ; public: Rostream() : std::ostream( new Buffer ), buf( static_cast( rdbuf() ) ) {} ~Rostream() { if (buf != NULL) { delete buf; buf = NULL; } } }; template <> inline std::streamsize Rstreambuf::xsputn(const char *s, std::streamsize num ) { Rprintf( "%.*s", static_cast(num), s ) ; return num ; } template <> inline std::streamsize Rstreambuf::xsputn(const char *s, std::streamsize num ) { REprintf( "%.*s", static_cast(num), s ) ; return num ; } template <> inline int Rstreambuf::overflow(int c) { if (c != traits_type::eof()) { char_type ch = traits_type::to_char_type(c); return xsputn(&ch, 1) == 1 ? c : traits_type::eof(); } return c; } template <> inline int Rstreambuf::overflow(int c) { if (c != traits_type::eof()) { char_type ch = traits_type::to_char_type(c); return xsputn(&ch, 1) == 1 ? c : traits_type::eof(); } return c; } template <> inline int Rstreambuf::sync(){ //::R_FlushConsole() ; return 0 ; } template <> inline int Rstreambuf::sync(){ //::R_FlushConsole() ; return 0 ; } TMB_EXTERN Rostream Rcout; TMB_EXTERN Rostream Rcerr; TMB/inst/include/fft.hpp0000644000176200001440000000335114536067013014573 0ustar liggesusers#include namespace atomic { template void fft_work(const CppAD::vector &x, CppAD::vector &y) { int ncplx = x.size() / 2; typedef std::complex C; C* X = (C*) x.data(); C* Y = (C*) y.data(); Eigen::FFT f; // How Eigen/FFT differs: invertible scaling is performed f.SetFlag(f.Unscaled); if (!adjoint) f.fwd(Y, X, ncplx); else f.inv(Y, X, ncplx); } TMB_ATOMIC_VECTOR_FUNCTION_DECLARE(fft) // So can be used by ifft TMB_ATOMIC_VECTOR_FUNCTION_DECLARE(ifft) // So can be used by fft TMB_ATOMIC_VECTOR_FUNCTION_DEFINE( fft, tx.size(), fft_work<0>(tx, ty), px = ifft(py)) TMB_ATOMIC_VECTOR_FUNCTION_DEFINE(ifft, tx.size(), fft_work<1>(tx, ty), px = fft(py)) /** \brief FFT (unscaled) \param xc Complex vector to be transformed \param inverse Apply the (unscaled) inverse transform? This interface is identical to 'stats::fft' so does **not** perform inverse scaling. \ingroup matrix_functions \note To use this function the header must be manually included. \note The default implementation is not the most efficient available. The more efficient FFTW library can be used by setting the preprocessor flag `EIGEN_FFTW_DEFAULT`. */ template vector > fft(vector > xc, bool inverse = false) { CppAD::vector x(2 * xc.size()); Type* px = x.data(); Type* pxc = (Type*) xc.data(); for (size_t i=0; i y; if (!inverse) y = atomic::fft(x); else y = atomic::ifft(x); px = (Type*) y.data(); for (size_t i=0; i Eigen::SparseMatrix asSparseMatrix(SEXP M){ int *i=INTEGER(R_do_slot(M,Rf_install("i"))); int *j=INTEGER(R_do_slot(M,Rf_install("j"))); double *x=REAL(R_do_slot(M,Rf_install("x"))); int n=LENGTH(R_do_slot(M,Rf_install("x"))); int *dim=INTEGER(R_do_slot(M,Rf_install("Dim"))); typedef Eigen::Triplet T; std::vector tripletList; for(int k=0;k mat(dim[0],dim[1]); mat.setFromTriplets(tripletList.begin(), tripletList.end()); return mat; } /** \brief Test if a scalar is a structural zero A **structural zero** is a scalar taking the value zero for all configurations of the model parameters. If the return value is `true` the input is guarantied to be a structural zero. \note Nothing can be deduced if the return value is `false`. For instance complex structural zeros such as \f$1-sin(x)^2-cos(x)^2\f$ won't be detected. */ template bool isStructuralZero(Type x) { return (x == Type(0)) && (! CppAD::Variable(x)); } /** \brief Create sparse matrix from dense matrix This function converts a dense matrix to a sparse matrix based on its numerical values. \note Zeros are detected using `isStructuralZero()` ensuring that entries which might become non-zero for certain parameter settings will not be regarded as zeros. */ template Eigen::SparseMatrix asSparseMatrix(matrix x){ typedef Eigen::Triplet T; std::vector tripletList; for(int i=0;i mat(x.rows(),x.cols()); mat.setFromTriplets(tripletList.begin(), tripletList.end()); return mat; } /** \brief Create sparse vector from dense vector This function converts a dense vector to a sparse vector based on its numerical values. \note Zeros are detected using `isStructuralZero()` ensuring that entries which might become non-zero for certain parameter settings will not be regarded as zeros. */ template Eigen::SparseVector asSparseVector(vector x){ typedef Eigen::Triplet T; std::vector tripletList; Eigen::SparseVector mat(x.rows()); for(int i=0;i Eigen::SparseMatrix kronecker(Eigen::SparseMatrix x, Eigen::SparseMatrix y){ typedef Eigen::Triplet T; typedef typename Eigen::SparseMatrix::InnerIterator Iterator; std::vector tripletList; int n1=x.rows(),n2=x.cols(),n3=y.rows(),n4=y.cols(); int i,j,k,l; // Loop over nonzeros of x for (int cx=0; cx mat(n1*n3,n2*n4); mat.setFromTriplets(tripletList.begin(), tripletList.end()); return mat; } /** Solve discrete Lyapunov equation V=AVA'+I */ template matrix discrLyap(matrix A_){ matrix I_(A_.rows(),A_.cols()); I_.setIdentity(); /* Sparse representations */ Eigen::SparseMatrix A=asSparseMatrix(A_); Eigen::SparseMatrix I=asSparseMatrix(I_); /* Kronecker */ Eigen::SparseMatrix AxA=kronecker(A,A); Eigen::SparseMatrix IxI=kronecker(I,I); matrix vecI=I_.vec().matrix(); Eigen::SparseMatrix C=IxI-AxA; /* Solve system C*vecV=vecI. Note: No assumptions on symmetry or eigenvalue-range of C. Therefore rewrite it as (C'*C)*vecV=(C*vecI). Since (C'*C) is symmetric, the LDL'-factorization can be applied. */ Eigen::SimplicialLDLT< Eigen::SparseMatrix > ldlt(C.transpose()*C); matrix z = ldlt.solve(C.transpose()*vecI); matrix V(A_.rows(),A_.cols()); for(int i=0;i matrix invertSparseMatrix(Eigen::SparseMatrix A){ matrix I(A.rows(),A.cols()); I.setIdentity(); Eigen::SimplicialLDLT< Eigen::SparseMatrix > ldlt(A); matrix ans = ldlt.solve(I); return ans; } } TMB/inst/include/tmbutils/density.hpp0000644000176200001440000013074314536067013017344 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file \brief Classes to construct multivariate **negative log** Gaussian density objects. \note These density classes return the **negative log likelihood**. */ /** \brief Collection of multivariate Gaussian distributions (members listed in \ref density.hpp) \ingroup Densities \details For use of the namespace see \ref Densities */ namespace density { using namespace tmbutils; #define TYPEDEFS(scalartype_) \ public: \ typedef scalartype_ scalartype; \ typedef vector vectortype; \ typedef matrix matrixtype; \ typedef array arraytype #define VARIANCE_NOT_YET_IMPLEMENTED \ private: \ vectortype variance(){return vectortype();} \ public: /** Conventions for simulation: \internal - The simulate method is pass by reference and modifies the input. So `Foo.simulate.(x);` fills `x` with a simulation. This is implemented for *all* classes. - For classes with unambiguous dimension (e.g. MVNORM, GMRF, ...) there is a simulate method with void input. It can be used as `x=Foo.simulate();`. Other classes (e.g. AR1, ARk) does not have this void argument version (attempt of use results in a compile time error). It follows that e.g. `SEPARABLE(AR1(phi), MVNORM(Sigma))` only has the void argument method whereas `SEPARABLE(MVNORM(Sigma), MVNORM(Sigma))` has both methods. - All classes must have a method `cov_sqrt_scale` that applied to a vector u returns "Sigma^(1/2) * u" for *some* square root. It is natural that this method is used by the simulate methods. This method is crucial for `SEPARABLE`. - All classes must have a `dim()` member. Attempt to call for un-supported classes gives compile time error. */ #define SIMULATE_NOT_YET_IMPLEMENTED \ private: \ vectortype sqrt_cov_scale(vectortype x){} \ void simulate(vectortype &u){} \ vectortype simulate(){} \ public: /* Add this macro to all classes with *dynamic* dimension (e.g. AR1) */ #define SIMULATE_IMPLEMENTED_UNKNOWN_SIZE \ void simulate(vectortype &x) { \ rnorm_fill(x); \ x = sqrt_cov_scale(x); \ x = zero_derivatives(x); \ } /* Add this macro to all classes with *fixed* dimension (e.g. MVNORM) */ #define SIMULATE_IMPLEMENTED_KNOWN_SIZE(SIZE) \ SIMULATE_IMPLEMENTED_UNKNOWN_SIZE \ vectortype simulate() { \ vectortype x(SIZE); \ simulate(x); \ return x; \ } /* Utility function: The simulators should not track derivatives when running with AD types. A workaround is to zero out the derivatives after simulation (FIXME: there is a minor efficiency loss by tracking the derivatives in the first place...). */ template arraytype zero_derivatives(arraytype x) { for(int i=0; i void rnorm_fill(arraytype &x) { for(int i=0; i Sigma(3,3); Sigma.fill(0.1); // Fill the whole matrix Sigma.diagonal() *= 10.0; // Multiply diagonal by 10 to positive definite Sigma vector x0(3); // Point of evaluation x0.fill(0.0); // Initialize x0 to be zero MVNORM_t N_0_Sigma(Sigma); // N_0_Sigma is now a Distribution res = N_0_Sigma(x0); // Evaluates (neg. log) density at x \endcode */ template class MVNORM_t{ TYPEDEFS(scalartype_); matrixtype Q; /* Inverse covariance matrix */ scalartype logdetQ; /* log-determinant of Q */ matrixtype Sigma; /* Keep for convenience - not used */ matrixtype L_Sigma; /* Used by simulate() */ public: MVNORM_t(){} MVNORM_t(matrixtype Sigma_, bool use_atomic=true){ setSigma(Sigma_, use_atomic); } /** \brief Covariance matrix extractor Typical use: \code matrix Sigma(3,3); MVNORM_t N_0_Sigma(Sigma); // N_0_Sigma is now a Distribution N_0_Sigma.cov(); // Returns covariance matrix (Sigma in this case) \endcode Useful for classes such as \ref UNSTRUCTURED_CORR_t that inherits from MVNORM_t. */ matrixtype cov(){return Sigma;} /* initializer via covariance matrix */ void setSigma(matrixtype Sigma_, bool use_atomic=true){ Sigma = Sigma_; scalartype logdetS; if(use_atomic){ Q = atomic::matinvpd(Sigma,logdetS); } else { matrixtype I(Sigma.rows(),Sigma.cols()); I.setIdentity(); Eigen::LDLT > ldlt(Sigma); Q = ldlt.solve(I); vectortype D = ldlt.vectorD(); logdetS = D.log().sum(); } logdetQ = -logdetS; } scalartype Quadform(vectortype x){ return (x*(vectortype(Q*x))).sum(); } /** \brief Evaluate the negative log density */ scalartype operator()(vectortype x){ return -scalartype(.5)*logdetQ + scalartype(.5)*Quadform(x) + x.size()*scalartype(log(sqrt(2.0*M_PI))); } /** \brief Evaluate _projected_ negative log density \param keep Vector of 0/1 indicating marginal to evaluate. */ scalartype operator()(vectortype x, vectortype keep){ matrix S = Sigma; vector not_keep = scalartype(1.0) - keep; for(int i = 0; i < S.rows(); i++){ for(int j = 0; j < S.cols(); j++){ S(i,j) = S(i,j) * keep(i) * keep(j); } S(i,i) += not_keep(i) * scalartype(1.0 / (2.0 * M_PI)); } return MVNORM_t(S)(x * keep); } arraytype jacobian(arraytype x){ arraytype y(x.dim); matrixtype m(x.size()/x.cols(),x.cols()); for(int i=0;i > llt(Sigma); L_Sigma = llt.matrixL(); } vectortype ans = L_Sigma * u; return ans; } SIMULATE_IMPLEMENTED_KNOWN_SIZE(Sigma.rows()); }; /** \brief Construct object to evaluate multivariate zero-mean normal density with user supplied covariance matrix \param Sigma Positive definite covariance matrix. \param use_atomic Determines if "atomic functions" are used for the linear algebra (default). Shortform version for working with the density of the \ref MVNORM_t distribution (C++ class). Typical use: \code MVNORM(Sigma)(x); \endcode where \c Sigma is a covariance matrix. The part \c MVNORM(Sigma) creates an object of MVNORM_t, which is then evaluated by the part \c (x). */ template MVNORM_t MVNORM(matrix Sigma, bool use_atomic = true){ return MVNORM_t(Sigma, use_atomic); } /** \brief Multivariate normal distribution with unstructered correlation matrix Class to evaluate the negative log density of a multivariate Gaussian variable with \b unstructured symmetric positive definite correlation matrix (*Sigma*). The typical application of this is that you want to estimate all the elements of *Sigma*, in such a way that the symmetry and positive definiteness constraint is respected. We parameterize *S* via a lower triangular matrix *L* with unit diagonal i.e. we need (n*n-n)/2 parameters to describe an n dimensional correlation matrix. For instance in the case n=4 the correlation matrix is given by \f[\Sigma = D^{-\frac{1}{2}}LL'D^{-\frac{1}{2}}\f] where \f[ L=\begin{pmatrix} 1 \\ \theta_0 & 1 \\ \theta_1 & \theta_2 & 1 \\ \theta_3 & \theta_4 & \theta_5 & 1 \end{pmatrix} \f] (lower triangle filled row-wise) and \f[ D=diag(LL') \f] Example: \code // Construct density object of dimension 4 vector theta(6); UNSTRUCTURED_CORR_t nll(theta); vector x(4); res = nll(x); // Evaluate neg. log density \endcode \remark *Sigma* is available via \ref MVNORM_t.cov , e.g. \code nll.cov(); \endcode \remarks *Sigma* has 1's on its diagonal. To scale the variances we can use \ref VECSCALE_t , e.g. \code vector sds(4); sds.fill(2.0); // Set all standard deviations to 2.0 res = VECSCALE_t(nll,sds)(x); \endcode */ template class UNSTRUCTURED_CORR_t : public MVNORM_t{ TYPEDEFS(scalartype_); UNSTRUCTURED_CORR_t(){} UNSTRUCTURED_CORR_t(vectortype x){ // (n*n-n)/2=nx ==> n*n-n-2*nx=0 ==> n=(1+sqrt(1+8*nx))/2 int nx=x.size(); int n=int((1.0+sqrt(1.0+8*nx))/2.0); if((n*n-n)/2!=nx)Rcout << "vector does not specify an UNSTRUCTERED_CORR\n"; matrixtype L(n,n); L.setIdentity(); int i,j,k=0; for(i=0;ij){L(i,j)=x[k];k++;} } } matrixtype llt=L*L.transpose(); matrixtype Sigma=llt; for(i=0;isetSigma(Sigma); /* Call MVNORM_t initializer */ } }; /** \brief Construct object to evaluate the density with unstructured correlation matrix. See UNSTRUCTURED_CORR_t for details */ template UNSTRUCTURED_CORR_t UNSTRUCTURED_CORR(vector x){ return UNSTRUCTURED_CORR_t(x); } /** \brief Standardized normal distribution Class to evaluate the negative log density of a (multivariate) standard normal distribution. \verbatim Examples: N01() \endverbatim */ template class N01{ TYPEDEFS(scalartype_); public: /** \brief Evaluate the negative log density */ scalartype operator()(scalartype x){ return x*x*.5 + log(sqrt(2.0*M_PI)); } scalartype operator()(vectortype x){ return (x*x*scalartype(.5) + scalartype(log(sqrt(2.0*M_PI))) ).sum() ; } scalartype operator()(arraytype x){ return (x*x*scalartype(.5) + scalartype(log(sqrt(2.0*M_PI))) ).sum() ; } arraytype jacobian(arraytype x){return x;} int ndim(){return 1;} VARIANCE_NOT_YET_IMPLEMENTED // FIXME: 1D will not suffice for e.g. SEPARABLE(N01, OTHER); vectortype simulate() { vectortype x(1); x[0] = rnorm(0.0, 1.0); return x; } // Inplace simulate void simulate(vectortype &x) { rnorm_fill(x); } vectortype sqrt_cov_scale(vectortype u) { return u; } }; /** \brief Stationary AR1 process Class to evaluate the negative log density of a (multivariate) AR1 process with parameter phi and given marginal distribution. @param phi Scalar -1 > f1(phi1); \\ Can be evaluated on a vector: vector x(10); Type ans=f1(x); \endcode Now use f1 as marginal in a new AR1 process with parameter phi2: \code \\ Construct negative log density of standard AR1 process on a line: Type phi2=0.5; AR1_t > > f2(phi1,f1); \\ Can be evaluated on a 2-dimensional array: vector x(10,20); Type ans=f2(x); \endcode */ template class AR1_t{ TYPEDEFS(typename distribution::scalartype); private: scalartype phi; distribution MARGINAL; public: AR1_t(){/*phi=phi_;MARGINAL=f_;*/} AR1_t(scalartype phi_, distribution f_) : phi(phi_), MARGINAL(f_) {} /** \brief Evaluate the negative log density */ scalartype operator()(vectortype x){ scalartype value; value=scalartype(0); int n=x.rows(); int m=x.size()/n; scalartype sigma=sqrt(scalartype(1)-phi*phi); /* Steady-state standard deviation */ value+=MARGINAL(x(0)); /* E.g. x0 ~ N(0,1) */ for(int i=1;i dim(2); dim << 1, u.size(); arraytype u_array(u, dim); return sqrt_cov_scale(u_array); } /** \brief Draw a simulation from the process */ void simulate(vectortype &x) { rnorm_fill(x); x = sqrt_cov_scale(x); x = zero_derivatives(x); } void simulate(arraytype &x) { rnorm_fill(x); x = sqrt_cov_scale(x); x = zero_derivatives(x); } }; template AR1_t AR1(scalartype phi_, distribution f_){ return AR1_t(phi_, f_); } template AR1_t > AR1(scalartype phi_){ return AR1_t >(phi_, N01()); } /** \brief Stationary AR(k) process. @param phi_ Vector of length k with parameters. \verbatim Class to evaluate the negative log density of a stationary AR(k)-process with parameter vector phi=[phi_1,...,phi_k]: x[t]=phi_1*x[t-1]+...+phi_k*x[t-k]+eps[t] where eps[t]~N(0,sigma^2). The parameter sigma^2 is chosen to obtain V(x[t])=1 so that the class actually specifies a correlation model. Examples: ARk(phi) <-- simple mean zero variance 1 AR(k) process. Steady state initial distribution is found by (e.g. k=3) [gamma(1)] [gamma(0) gamma(1) gamma(2)] [phi1] [ .... ] = [gamma(1) gamma(0) gamma(1)] * [phi2] [gamma(3)] [gamma(2) gamma(1) gamma(0)] [phi3] \endverbatim */ template class ARk_t{ TYPEDEFS(scalartype_); //private: int k; vectortype phi; /* [phi1,...,phik] */ vectortype gamma; /* [gamma(1),...,gamma(k)] (note gamma(0) is 1) */ /* Initial distribution matrices. */ matrixtype V0; /* kxk variance */ matrixtype Q0; /* kxk precision */ matrixtype L0; /* kxk Cholesky Q0 = L0*L0' */ /* gamma is found through (I-M)*gamma=phi ... */ matrixtype M; /* kxk */ matrixtype I; /* kxk */ scalartype sigma;/* increment standard deviation */ scalartype logdetQ0; public: ARk_t(){/*phi=phi_;MARGINAL=f_;*/} ARk_t(vectortype phi_){ phi=phi_; k=phi.size(); V0.resize(k,k);Q0.resize(k,k); M.resize(k,k);I.resize(k,k); /* build M-matrix */ M.setZero(); int d; for(int i=0;i ARk_t ARk(vector phi){ return ARk_t(phi); } /** \brief Continuous AR(2) process \verbatim Process with covariance satisfying the 2nd order ode rho''=c1*rho'-rho on an arbitrary irregular grid. (shape=c1/2, -1 class contAR2_t{ TYPEDEFS(scalartype_); private: typedef Matrix matrix2x2; typedef Matrix matrix2x1; typedef Matrix matrix4x4; typedef Matrix matrix4x1; scalartype shape,scale,c0,c1; vectortype grid; matrix2x2 A, V0, I; matrix4x4 B, iB; /* B=A %x% I + I %x% A */ matexp expA; matrix4x1 vecSigma,iBvecSigma; vector > neglogdmvnorm; /* Cache the 2-dim increments */ vector expAdt; /* Cache matrix exponential for grid increments */ public: contAR2_t(){}; contAR2_t(vectortype grid_, scalartype shape_, scalartype scale_=1){ shape=shape_;scale=scale_;grid=grid_; c0=scalartype(-1);c1=scalartype(2)*shape_; c0=c0/(scale*scale); c1=c1/scale; A << scalartype(0), scalartype(1), c0, c1; V0 << 1,0,0,-c0; I.setIdentity(); B=kronecker(I,A)+kronecker(A,I); iB=B.inverse(); expA=matexp(A); vecSigma << 0,0,0,scalartype(-2)*c1*V0(1,1); iBvecSigma=iB*vecSigma; /* cache increment distribution N(0,V(dt)) - one for each grid point */ neglogdmvnorm.resize(grid.size()); neglogdmvnorm[0]=MVNORM_t(V0); for(int i=1;i(V(grid(i)-grid(i-1))); /* cache matrix exponential */ expAdt.resize(grid.size()); expAdt[0]=expA(scalartype(0)); for(int i=1;i dim(2); dim << 2 , x.size()/2 ; array y(x,dim); y=y.transpose(); return this->operator()(y.col(0),y.col(1)); } arraytype matmult(matrix2x2 Q,arraytype x){ arraytype y(x.dim); y.col(0) = Q(0,0)*x.col(0)+Q(0,1)*x.col(1); /* TODO: can we subassign like this in array class? Hack: we use "y.row" for that */ y.col(1) = Q(1,0)*x.col(0)+Q(1,1)*x.col(1); return y; } arraytype jacobian(arraytype x){ arraytype y(x.dim); y.setZero(); arraytype tmp(y(0).dim); y.col(0) = neglogdmvnorm[0].jacobian(x.col(0)); /* Time zero contrib */ for(int i=1;i contAR2_t contAR2(vectortype grid_, scalartype shape_, scalartype scale_=1){ return contAR2_t(grid_, shape_, scale_); } template contAR2_t contAR2(scalartype shape_, scalartype scale_=1){ return contAR2_t(shape_, scale_); } /** \brief Gaussian Markov Random Field \verbatim Class to evaluate the negative log density of a mean zero multivariate normal distribution with a sparse precision matrix. Let Q denote the precision matrix. Then the density is proportional to |Q|^.5*exp(-.5*x'*Q*x) Three constructors are available: 1. General case =============== The user supplies the precision matrix Q of class Eigen::SparseMatrix 2. Special case: GMRF on d-dimensional lattice. =============================================== The user supplies a d-dim lattice for which Q is automatically constructed like this: First order Gaussian Markov Random Field on (subset of) d-dim grid. Grid is specified through the first array argument to constructor, with individual nodes determined by the outdermost dimension e.g. x= 1 1 2 2 1 2 1 2 corresponding to a 2x2 lattice with 4 nodes and d=2. Example of precision in 2D: -1 -1 4+c -1 -1 The precision Q is convolved with it self "order" times. This way more smoothness can be obtained. The quadratic form contribution is .5*x'*Q^order*x 3. Vector of deltas =================== The parameter "delta" describes the (inverse) correlation. It is allowed to specify a vector of deltas so that different spatial regions can have different spatial correlation. NOTE: The variance in the model depends on delta. In other words: The model may be thought of as an arbitrary scaled correlation model and is thus not really meaningful without an additional scale parameter (see SCALE_t and VECSCALE_t classes). \endverbatim */ template class GMRF_t { TYPEDEFS(scalartype_); private: Eigen::SparseMatrix Q; scalartype logdetQ; int sqdist(vectortype x, vectortype x_) { int ans = 0; int tmp; for(int i=0; i Q_, int order_=1, bool normalize=true){ setQ(Q_, order_, normalize); } GMRF_t(arraytype x, vectortype delta, int order_=1, bool normalize=true){ int n = x.cols(); typedef Eigen::Triplet T; std::vector tripletList; for(int i=0; i Q_(n, n); Q_.setFromTriplets(tripletList.begin(), tripletList.end()); setQ(Q_, order_, normalize); } void setQ(Eigen::SparseMatrix Q_, int order=1, bool normalize=true){ Q = Q_; if (normalize) { #ifndef TMBAD_FRAMEWORK Eigen::SimplicialLDLT< Eigen::SparseMatrix > ldl(Q); vectortype D = ldl.vectorD(); logdetQ = (log(D)).sum(); #else logdetQ = newton::log_determinant(Q); #endif } else { logdetQ = 0; } /* Q^order */ for(int i=1; i L; Eigen::PermutationMatrix Pinv; vectortype sqrt_cov_scale(vectortype u) { if(L.rows() == 0) { Eigen::SimplicialLLT > solver(Q); L = solver.matrixL(); Pinv = solver.permutationPinv(); } // L*L^T = P*Q*Pinv => Q^-1 = A*A^T where A:=P^-1*L^T^-1 matrixtype x = L.transpose().template triangularView().solve(u.matrix()); x = Pinv * x; return x.vec(); } SIMULATE_IMPLEMENTED_KNOWN_SIZE(Q.rows()) }; /** \brief Construct object to evaluate density of Gaussian Markov Random Field (GMRF) for sparse Q For detailed explanation of GMRFs see the class definition @ref GMRF_t \param Q precision matrix \param order Convolution order, i.e. the precision matrix is Q^order (matrix product) \param normalize Add normalizing constant ? */ template GMRF_t GMRF(Eigen::SparseMatrix Q, int order, bool normalize=true) { return GMRF_t(Q, order, normalize); } template GMRF_t GMRF(arraytype x, vector delta, int order=1, bool normalize=true) { return GMRF_t(x, delta, order, normalize); } template GMRF_t GMRF(arraytype x, scalartype delta, int order=1, bool normalize=true) { vector d(x.cols()); for(int i=0; i(x, d, order, normalize); } template GMRF_t GMRF(Eigen::SparseMatrix Q, bool normalize = true) { return GMRF_t(Q, 1, normalize); } /** \brief Apply scale transformation on a density Assume x has density f. Construct the density of y=scale*x where scale is a scalar. @param f_ distribution @param scale_ scalar */ template class SCALE_t{ TYPEDEFS(typename distribution::scalartype); private: distribution f; scalartype scale; public: SCALE_t(){} SCALE_t(distribution f_, scalartype scale_){scale=scale_;f=f_;} /** \brief Evaluate the negative log density */ scalartype operator()(arraytype x){ scalartype ans=f(x/scale); ans+=x.size()*log(scale); return ans; } scalartype operator()(vectortype x){ scalartype ans=f(x/scale); ans+=x.size()*log(scale); return ans; } arraytype jacobian(arraytype x){ return f.jacobian(x/scale)/scale; } int ndim(){return f.ndim();} vectortype variance(){ return (scale*scale)*f.variance(); } vectortype sqrt_cov_scale(vectortype u){ return scale * f.sqrt_cov_scale(u); } SIMULATE_IMPLEMENTED_UNKNOWN_SIZE }; template SCALE_t SCALE(distribution f_, scalartype scale_){ return SCALE_t(f_,scale_); } /** \brief Apply a vector scale transformation on a density Assume x has density f. Construct the density of y=scale*x where scale is a vector. @param f_ distribution @param scale_ vector \remark To scale the standard deviations of a unit-variance multivariate normal distribution of class UNSTRUCTURED_CORR_t: \code vector Lx(6); UNSTRUCTURED_CORR_t nll(Lx); vector sds(4); sds.fill(2.0); // Set all standard deviations to 2.0 res = VECSCALE_t(nll,sds)(x); \endcode \remark Another application is to scale the variance of a unit-variance AR(1) process; see \ref AR1_t . */ template class VECSCALE_t{ TYPEDEFS(typename distribution::scalartype); private: distribution f; vectortype scale; public: VECSCALE_t(){} VECSCALE_t(distribution f_, vectortype scale_){scale=scale_;f=f_;} /** \brief Evaluate the negative log density */ scalartype operator()(arraytype x){ // assert that x.size()==scale.size() scalartype ans=f(x/scale); ans+=(log(scale)).sum(); return ans; } scalartype operator()(vectortype x){ // assert that x.size()==scale.size() scalartype ans=f(x/scale); ans+=(log(scale)).sum(); return ans; } arraytype jacobian(arraytype x){ // assert that x.rows()==scale.size() arraytype y(x); for(int i=0;i VECSCALE_t VECSCALE(distribution f_, vectortype scale_){ return VECSCALE_t(f_,scale_); } /** \brief Separable extension of two densitites Take two densities f and g, and construct the density of their separable extension, defined as the multivariate Gaussian distribution with covariance matrix equal to the kronecker product between the covariance matrices of the two distributions. Note that f acts on the outermost array dimension and g acts on the fastest running array dimension. \verbatim More precisely: evaluate density h(x)=|S/(2*pi)|^.5*exp(-.5*x'*S*x) where S=kronecker(Q,R)=Q%x%R assuming we have access to densities f(x)=|Q/(2*pi)|^.5*exp(-.5*x'*Q*x) g(x)=|R/(2*pi)|^.5*exp(-.5*x'*R*x) (Note: R corresponds to fastest running array dimension in Q%x%R ...) Let nq=nrow(Q) and nr=nrow(R), using rules of the kronecker product we have that * Quadratic form = .5*x'*S*x = .5*x'*(Q%x%I)*(I%x%R)*x * Normalizing constant = |S/(2*pi)|^.5 = |(Q/sqrt(2*pi))%x%(R/sqrt(2*pi))|^.5 = |(Q/sqrt(2*pi))|^(nr*.5) |(R/sqrt(2*pi))|^(nq*.5) = ... something that can be expressed through the normalizing constants f(0) and g(0) ... f(0)^nr * g(0)^nq * sqrt(2*pi)^(nq*nr) \endverbatim Example: \code // Separable extension of two AR1 processes Type phi1=0.8; AR1_t > f(phi1); Type phi2=0.8; AR1_t > g(phi2); SEPARABLE_t > , AR1_t > > h(f,g); // Can be evaluated on an array: array x(10,20); Type ans=h(x); \endcode */ //template template class SEPARABLE_t{ TYPEDEFS(typename distribution1::scalartype); private: distribution1 f; distribution2 g; public: SEPARABLE_t(){} SEPARABLE_t(distribution1 f_, distribution2 g_){f=f_;g=g_;} /* Example: x.dim=[n1,n2,n3]. Apply f on outer dimension (n3) and rotate: [n3,n1,n2] Apply g on new outer dimension (n2) and rotate back: [n1,n2,n3] */ arraytype jacobian(arraytype x){ int n=f.ndim(); x=f.jacobian(x); x=x.rotate(n); x=g.jacobian(x); x=x.rotate(-n); return x; } /* Create zero vector corresponding to the last n dimensions of dimension-vector d */ arraytype zeroVector(vector d, int n){ int m=1; vector revd=d.reverse(); vector revnewdim(n); for(int i=0;indim() != x.dim.size())Rcout << "Wrong dimension in SEPARABLE_t\n"; /* Calculate quadform */ arraytype y(x.dim); y=jacobian(x); y=x*y; /* pointwise */ scalartype q=scalartype(.5)*(y.sum()); /* Add normalizing constant */ int n=f.ndim(); arraytype zf=zeroVector(x.dim,n); q+=f(zf)*(scalartype(x.size())/scalartype(zf.size())); x=x.rotate(n); int m=g.ndim(); arraytype zg=zeroVector(x.dim,m); q+=g(zg)*(scalartype(x.size())/scalartype(zg.size())); q-=log(sqrt(2.0*M_PI))*(zf.size()*zg.size()); /* done */ return q; } int ndim(){return f.ndim()+g.ndim();} VARIANCE_NOT_YET_IMPLEMENTED /* For parallel accumulation: ========================== Copied operator() above and added extra argument "i" to divide the accumulation in chunks. The evaluation of operator()(x) is equivalent to summing up operator()(x,i) with i running through the _outer_dimension_ of x. */ scalartype operator()(arraytype x, int i){ if(this->ndim() != x.dim.size())Rcout << "Wrong dimension in SEPARABLE_t\n"; /* Calculate quadform */ arraytype y(x.dim); y=jacobian(x); y=x*y; /* pointwise */ scalartype q=scalartype(.5)*(y.col(i).sum()); /* Add normalizing constant */ if(i==0){ int n=f.ndim(); arraytype zf=zeroVector(x.dim,n); q+=f(zf)*(scalartype(x.size())/scalartype(zf.size())); x=x.rotate(n); int m=g.ndim(); arraytype zg=zeroVector(x.dim,m); q+=g(zg)*(scalartype(x.size())/scalartype(zg.size())); q-=log(sqrt(2.0*M_PI))*(zf.size()*zg.size()); } /* done */ return q; } arraytype sqrt_cov_scale(arraytype u) { vector u_dim = u.dim; vector f_dim = u_dim.tail(f.ndim()); vector g_dim = u_dim.head(g.ndim()); int f_size = f_dim.prod(); int g_size = g_dim.prod(); // Collapse f dimension to a single dimension: vector new_dim(g.ndim() + 1); new_dim << g_dim, f_size; u.setdim(new_dim); for(int i=0; i SEPARABLE_t SEPARABLE(distribution1 f_, distribution2 g_){ return SEPARABLE_t(f_,g_); } /** \brief Projection of multivariate gaussian variable. Preserves sparseness if possible. Generally it is not. \verbatim Given a gaussian density f:R^n -> R. Given an integer vector "proj" with elements in 1,...,n. Construct the mariginal density of "x[proj]". Details: -------- Let x=[x_A] [x_B] with precision Q=[Q_AA Q_AB] [Q_BA Q_BB] and assume that proj=A. The marginal density is (with notation 0:=0*x_B ) p_A(x_A)=p(x_A,x_B)/p(x_B|x_A)=p(x_A,0)/p(0|x_A) Now see that 1. p(x_A,0) is easy because full precision is sparse. 2. p(0|x_A) is N(-Q_BB^-1 * Q_BA x_A, Q_BB^-1) so p(0|x_A) = |Q_BB|^.5 * exp(-.5*x_A Q_AB * Q_BB^-1 * Q_BA x_A) Trick to evaluate this with what we have available: Note 1: Q_BA x_A = [0 I_BB] * full_jacobian([ x_A ] [ 0 ] ) Call this quantity "y_B" we have p(0|x_A) = |Q_BB|^.5 * exp(-.5*y_B' * Q_BB^-1 * y_B) Note 2: Consider now a density with _covariance_ Q_BB phi(y)=|Q_BB|^-.5 * exp(-.5*y' * Q_BB^-1 * y) Then phi(y)/phi(0)^2=|Q_BB|^.5 * exp(-.5*y' * Q_BB^-1 * y) which is actually the desired expression of p(0|x_A). Summary: ------- Negative log-density of A-marginal is -log p(x_A,0) + log phi(y) - 2*log(phi(0)) = f(x_A,0) - dmvnorm(y_B) + 2*dmvnorm(0) \endverbatim */ template class PROJ_t{ TYPEDEFS(typename distribution::scalartype); private: distribution f; bool initialized; public: vector proj; vector cproj; /* complementary proj _sorted_ */ int n,nA,nB; matrixtype Q; /* Full precision */ MVNORM_t dmvnorm; /* mean zero gaussian with covariance Q_BB */ PROJ_t(){} PROJ_t(distribution f_, vector proj_){ f=f_; proj=proj_; initialized=false; } void initialize(int n_){ if(!initialized){ n=n_; nA=proj.size(); nB=n-nA; cproj.resize(nB); vector mark(n); mark.setZero(); for(int i=0;i dim(2); dim << n,n; arraytype a(v,dim); a=f.jacobian(a); Q.resize(n,n); for(int i=0;i(QBB); } initialized=true; } vectortype projB(vectortype x){ vectortype y(nB); for(int i=0;i dim(1); dim << x.size(); arraytype xa(x,dim); vectortype y=projB(f.jacobian(xa)); // f(x_A,0) - dmvnorm(y_B) + 2*dmvnorm(0) return f(xa) - dmvnorm(y) + 2*dmvnorm(y*scalartype(0)); } /* array versions */ arraytype projB(arraytype x){ vectortype z((x.size()/n)*nB); vector dim(x.dim); dim[dim.size()-1]=nB; arraytype y(z,dim); for(int i=0;i return f.jacobian(xa) - dmvnorm.jacobian(y); // y=P*Q*Z*x so should be (P*Q*Z)' * dmvnorm.jacobian(y). // Note: only P is not symmetric. arraytype tmp=f.jacobian(xa); arraytype tmp0=tmp*scalartype(0); arraytype tmp2=dmvnorm.jacobian(y); // apply P' for(int i=0;i PROJ_t PROJ(distribution f_, vector i){ return PROJ_t(f_,i); } #undef TYPEDEFS } // End namespace TMB/inst/include/tmbutils/interpol.hpp0000644000176200001440000001671214536067013017520 0ustar liggesusers/** \file \brief Atomic interpolation operator. \note Available for TMBad framework only. */ #ifdef TMBAD_FRAMEWORK #include namespace tmbutils { /** \brief Configuration for `Interpol2D` */ template struct interpol2D_config { interpol2D_config(Type R=2) : R(asDouble(R)), safe_check(true) { } /** \brief Interpolation radius relative to integer lattice \details - `R` measures degree of smoothness. Default value: `R=2`. - Interpolation is only matching exact measurements if `R<=1`. - NaN returned outside boundaries - NA data values are allowed and will be given zero weight. */ double R; /** \brief Enable safety check that data really are constant? */ bool safe_check; }; template struct interpol2Dtab { matrix data; double xmin, xmax, ymin, ymax; interpol2D_config cfg; /** \brief Base kernel \details Properties - f(0) = 1, f(.5) = .5, f(1) = 0 - Derivatives to 1st order are zero. */ template T f(T x) { return .5 * ( 1 + cos(x * M_PI) ) ; } /** \brief Smooth kernel by iterating. \details Properties - f(0) = 1, f(.5) = .5, f(1) = 0 - Derivatives to 3rd order are zero. */ template T kernel(T x) { return f(1 - f(x)) ; } // helper template T sq(T x) { return x * x; } /** \brief Do interpolation at (x_,y_) \details Works with `double` or `tiny_ad`. */ template T eval(T x_, T y_) { double R = cfg.R; int nrow = data.rows(); int ncol = data.cols(); T hx = (xmax - xmin) / (nrow - 1); T hy = (ymax - ymin) / (ncol - 1); // Transform (x_, y_) to 'lattice coordinates': T i_ = (x_ - xmin) / hx; T j_ = (y_ - ymin) / hy; // Check bool ok = (0 <= i_) && (i_ <= nrow-1) && (0 <= j_) && (j_ <= ncol-1); if (!ok) return R_NaN; // Envelope window: W := (i_, j_) + [-R, R]^2 // Get sub-lattice within envelope: (i_min:i_max) x (j_min:j_max) int i_min = std::max(asDouble(i_) - R, (double) 0); int j_min = std::max(asDouble(j_) - R, (double) 0); int i_max = std::min(asDouble(i_) + R, (double) (nrow-1) ); int j_max = std::min(asDouble(j_) + R, (double) (ncol-1) ); // Loop through sub-lattice T FWsum = 0, Wsum = 0; for (int i = i_min; i <= i_max; i++) { for (int j = j_min; j <= j_max; j++) { T dist2 = sq( (T) i - i_ ) + sq( (T) j - j_ ) ; double tiny = 1e-100; T dist = sqrt( dist2 + tiny ); if (dist <= R) { double F = data(i, j); if (! ISNA(F) ) { T W = kernel(dist / R); FWsum += F * W; Wsum += W; } } } } return FWsum / Wsum; } /** \brief Helper to get derivatives */ template double D_eval(double x_, double y_, int ny) { typedef atomic::tiny_ad::variable T; int i = (1 << ny) - 1; T x(x_, 0); T y(y_, 1); return eval(x, y).getDeriv()[i]; } /** \brief Interpolation and derivatives up to 3rd order */ double operator()(double x_, double y_, int nx=0, int ny=0) { int order = nx + ny; if (order == 0) { return eval(x_, y_); } else if (order == 1) { return D_eval<1>(x_, y_, ny); } else if (order == 2) { return D_eval<2>(x_, y_, ny); } else if (order == 3) { return D_eval<3>(x_, y_, ny); } else { Rf_error("Order not implemented"); } return 0; } }; /** \brief Get a smooth representation of a **data** matrix. \details This 2D interpolation can be put on the AD tape. Interpolation data is shared among instances so you can do interpolation many times without duplicating the data. In addition the operator is thread safe, whether used with manual parallelization (`parallel_accumulator` etc) or automatic parallization (`TMBad::autopar`). The actual interpolation is based on a kernel smoothing approach: To obtain the interpolated value at coordinate (x,y), the coordinate is first transformed to continous matrix index coordinates using the supplied `x_range` and `y_range`. The distance to each matrix entry `d(i,j)` is then calculated, and a corresponding 'weight' is given as a function (kernel) of the distance divided by the 'interpolation radius' (R), i.e. `W(i,j)=kernel(d(i,j)/R)`. The final interpolated value becomes `sum(W*F)/sum(W)` where `F` is the data matrix. We note that the interpolation radius (interpol2D_config::R) is relative to matrix index coordinates (and is thus not related to the `x_range` and `y_range`). \note An error is triggered if some data are not constant */ template struct interpol2D : TMBad::global::DynamicOperator<2, 1> { std::shared_ptr > dtab; int xorder, yorder; matrix asDoubleCheck(matrix x, bool do_check=true) { matrix y(x.rows(), x.cols()); for (int i=0; i data, vector x_range, vector y_range, interpol2D_config cfg=interpol2D_config() ) : dtab(std::make_shared >(interpol2Dtab({ asDoubleCheck(data, cfg.safe_check), asDouble(x_range[0]), asDouble(x_range[1]), asDouble(y_range[0]), asDouble(y_range[1]), cfg }))), xorder(0), yorder(0) { } TMBad::Index input_size() const { return 2; } TMBad::Index output_size() const { return 1; } typedef TMBad::ad_aug ad; /** \brief Scalar evaluation with double types \param x x-coordinate \param y y-coordinate \param nx x-derivative order \param ny y-derivative order */ double operator()(double x, double y, int nx=0, int ny=0) { return (*dtab)(x, y, nx, ny); } /** \brief Scalar evaluation with ad types \param x x-coordinate \param y y-coordinate \param nx x-derivative order \param ny y-derivative order */ ad operator()(ad x, ad y, int nx=0, int ny=0) { std::vector xy(2); xy[0]=x; xy[1]=y; interpol2D cpy(*this); cpy.xorder = nx; cpy.yorder=ny; std::vector z = TMBad::global::Complete(cpy)(xy); return z[0]; } #define Type T VECTORIZE2_tt(operator()) #undef Type // Forward pass template void forward(TMBad::ForwardArgs &args) { args.y(0) = (*this)(args.x(0), args.x(1), xorder, yorder); } // Reverse pass template void reverse(TMBad::ReverseArgs &args) { T dy = args.dy(0); args.dx(0) += (*this)(args.x(0), args.x(1), xorder + 1, yorder) * dy; args.dx(1) += (*this)(args.x(0), args.x(1), xorder, yorder + 1) * dy; } // sources code writers are not implemented for this class void forward(TMBad::ForwardArgs &args) { ASSERT(false); } void reverse(TMBad::ReverseArgs &args) { ASSERT(false); } const char* op_name() { return "IP2D"; } }; } #endif TMB/inst/include/tmbutils/kronecker.hpp0000644000176200001440000000170114536067013017637 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file \brief Kronecker product of two matrices */ namespace tmbutils { /** \brief Kronecker product of two matrices */ template Matrix kronecker(Matrix x, Matrix y){ Matrix ans; for(int i=0;i matrix kronecker(matrix x, matrix y){ int n1 = x.rows(), n2 = x.cols(), n3 = y.rows(), n4 = y.cols(); matrix ans(n1 * n3, n2 * n4); for(int i=0;i template struct univariate { Type theta; // Parameter in integrand univariate(Type theta_) // Constructor of integrand : theta (theta_) {} // Initializer list Type operator()(Type x){ // Evaluate integrand return exp( -theta * (x * x) ); } }; template Type objective_function::operator() () { DATA_SCALAR(a); DATA_SCALAR(b); PARAMETER(theta); univariate f(theta); Type res = romberg::integrate(f, a, b); return res; } \endcode */ template Type integrate(F f, Type a, Type b, int n = 7, int p = 2){ Type e; return CppAD::RombergOne(f, a, b, n, p, e); } /* Construct 1D slice of vector function */ template struct slicefun{ F* f; vector x; int slice; slicefun(F* f_, vector x_, int slice_) { f=f_; x=x_; slice=slice_; } Type operator()(Type y){ x(slice) = y; return f->operator()(x); } }; /* integrate along i'th slice, f vector function */ template Type integrate_slice(F &f, vector x, int i, Type a, Type b, int n=7, int p=2){ return integrate(slicefun(&f, x, i), a, b, n, p); } template struct multivariate_integrand{ virtual Type operator()(vector) = 0; }; template struct integratelast : multivariate_integrand{ slicefun >* fslice; int n, p; Type a, b; integratelast(multivariate_integrand &f, int dim, Type a_, Type b_, int n_ = 7, int p_ = 2){ int slice = dim - 1; vector x(dim); fslice = new slicefun >(&f, x, slice); n=n_; p=p_; a=a_; b=b_; } ~integratelast(){delete fslice;} Type operator()(vector y){ for(int i=0; i < y.size(); i++) fslice->x[i] = y[i]; return integrate(*fslice, a, b, n, p); } }; template Type integrate_multi(multivariate_integrand &f, vector a, vector b, int n = 7, int p = 2){ int dim = a.size(); integratelast ffirst(f, dim, a(dim - 1), b(dim - 1), n, p); if(dim == 1){ vector y(0); return ffirst(y); } else { vector afirst = a.segment(0, dim - 1); vector bfirst = b.segment(0, dim - 1); return integrate_multi(ffirst, afirst, bfirst, n, p); } } /** \brief Multi-dimensional numerical integration using Romberg's method. Dimension need not be known at compile time. \param f Multivariate functor \param a Lower vector integration limit \param b Upper vector integration limit \param n Subdivisions per dimension (\f$(2^{n-1}+1)^d\f$ function evaluations). \note The method is not adaptive and the user may have to specify a larger n. Example: \code #include template struct multivariate { Type theta; // Parameter in integrand multivariate(Type theta_) // Constructor of integrand : theta (theta_) {} // Initializer list Type operator() // Evaluate integrand (vector x){ return exp( -theta * (x * x).sum() ); } }; template Type objective_function::operator() () { DATA_VECTOR(a); DATA_VECTOR(b); PARAMETER(theta); multivariate f(theta); Type res = romberg::integrate(f, a, b); return res; } \endcode */ template Type integrate(F f, vector a, vector b, int n=7, int p=2){ // Wrap f in container struct integrand : multivariate_integrand{ F f; integrand(F f_) : f(f_) {} Type operator()(vector x){ return f(x); } }; integrand f_cpy(f); return integrate_multi(f_cpy, a, b, n, p); } } TMB/inst/include/tmbutils/matexp.hpp0000644000176200001440000000367514536067013017166 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file \brief Matrix exponential. */ namespace tmbutils { /** \brief Matrix exponential: matrix of arbitrary dimension. */ template struct matexp{ typedef Matrix matrix; typedef Matrix ,dim,dim> cmatrix; typedef Matrix ,dim,1> cvector; cmatrix V; cmatrix iV; cvector lambda; EigenSolver< matrix > eigensolver; matexp(){}; matexp(matrix A_){ eigensolver.compute(A_); V=eigensolver.eigenvectors(); lambda=eigensolver.eigenvalues(); iV=V.inverse(); } matrix operator()(scalartype t){ cmatrix tmp; tmp.setZero(); matrix ans; for(int i=0;i struct matexp{ typedef std::complex complex; typedef Matrix matrix; typedef Matrix cmatrix; typedef Matrix cvector; cmatrix V; cmatrix iV; cvector lambda; matexp(){}; matexp(matrix A_){ complex T=scalartype(0.5)*A_.trace(); /* half trace */ complex D=A_.determinant(); lambda << T+sqrt(T*T-D) , T-sqrt(T*T-D); scalartype a=A_(0,0); scalartype b=A_(0,1); V << b, b, lambda(0)-a, lambda(1)-a; iV=V.inverse(); } matrix operator()(scalartype t){ int dim=2; cmatrix tmp; tmp.setZero(); matrix ans; for(int i=0;i struct vector : TMBad::ad_segment { typedef TMBad::ad_segment Base; using Base::Base; vector() {} // Surprisingly, needed on some systems. vector(tmbutils::vector x) : Base(x.data(), x.size()) { } vector(const Base &x) : Base(x) { } operator std::vector() const { std::vector x(this->size()); for (size_t i=0; isize(); i++) x[i] = (*this)[i]; return x; } operator tmbutils::vector() const { tmbutils::vector x(this->size()); for (size_t i=0; isize(); i++) x[i] = (*this)[i]; return x; } tmbutils::vector array() const { return *this; } Type sum() const { return TMBad::sum(*this); } }; template <> struct vector : tmbutils::vector { typedef tmbutils::vector Base; using Base::Base; vector() {} // Surprisingly, needed on some systems. vector(tmbutils::vector x) : Base(x) { } }; /** \brief Demonstrate native vectorization of 'dnorm' */ template vector dnorm(vector x, T1 mean, T2 sd, int give_log=0) { vector logres; x = (x - mean) / sd; logres = -log(Type(sqrt(2*M_PI)) * sd) - Type(.5) * x * x; if(give_log) return logres; else return exp(logres); } } // End namespace #endif TMB/inst/include/tmbutils/array.hpp0000644000176200001440000002353514536067013017003 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file vector.hpp Array templates using inheritance. */ /** \brief Array class used by TMB. The TMB array class is implemented as an Eigen Array of dynamic length with a dimension attribute. The implementation closely follows the way arrays work in R. Vectorized operations are inherited from the Eigen library. \warning Methods that are not documented here are inherited from the Eigen library and applied on the underlying n-by-1 array. In general this will yield surprising results for 2D specific array methods. */ template struct array:Map< Array >{ typedef Array Base; typedef Map< Base > MapBase; vector dim; /* def: inner product sum(mult*tuple) gives vector index example: array a(4,5,6); dim=[4,5,6] first dimension runs fastest, last dimension slowest: mult=[1,1*4,1*4*5] */ vector mult; Base vectorcopy; /* Array data */ /** \brief Sets dimension attribute and updates internal stride. **Must** be used when e.g. collapsing array dimensions. */ void setdim(vector dim_){ dim=dim_; mult.resize(dim.size()); mult[0]=1; for(int k=1;k dim_){ vectorcopy.resize(dim_.prod()); vectorcopy.setZero(); if (vectorcopy.size() > 0) { new (this) MapBase(&vectorcopy[0],vectorcopy.size()); /* Eigen manual: Despite appearances, this does not invoke the memory allocator... */ } setdim(dim_); } /* Utility function */ vector c(int n1){ vector ans(1); ans << n1; return ans; } vector c(int n1, int n2){ vector ans(2); ans << n1,n2; return ans; } vector c(int n1, int n2, int n3){ vector ans(3); ans << n1,n2,n3; return ans; } vector c(int n1, int n2, int n3, int n4){ vector ans(4); ans << n1,n2,n3,n4; return ans; } vector c(int n1, int n2, int n3, int n4, int n5){ vector ans(5); ans << n1,n2,n3,n4,n5; return ans; } vector c(int n1, int n2, int n3, int n4, int n5, int n6){ vector ans(6); ans << n1,n2,n3,n4,n5,n6; return ans; } vector c(int n1, int n2, int n3, int n4, int n5, int n6, int n7){ vector ans(7); ans << n1,n2,n3,n4,n5,n6,n7; return ans; } /* Default constructor: e.g. array a; */ array():MapBase(NULL,0){}; /** \brief Construct array from dimension vector and fill with zeros. */ array(vector dim_):MapBase(NULL,0){ initZeroArray(dim_); } array(int n1):MapBase(NULL,0){initZeroArray(c(n1));} array(int n1, int n2):MapBase(NULL,0){initZeroArray(c(n1,n2));} array(int n1, int n2, int n3):MapBase(NULL,0){initZeroArray(c(n1,n2,n3));} array(int n1, int n2, int n3, int n4):MapBase(NULL,0){initZeroArray(c(n1,n2,n3,n4));} array(int n1, int n2, int n3, int n4, int n5):MapBase(NULL,0){initZeroArray(c(n1,n2,n3,n4,n5));} array(int n1, int n2, int n3, int n4, int n5, int n6):MapBase(NULL,0){initZeroArray(c(n1,n2,n3,n4,n5,n6));} array(int n1, int n2, int n3, int n4, int n5, int n6, int n7):MapBase(NULL,0){initZeroArray(c(n1,n2,n3,n4,n5,n6,n7));} /* Default construction: always deep copy ! */ template array(T &x, vector dim_):MapBase(NULL,0),vectorcopy(x){ if(x.size()>0){ new (this) MapBase(&vectorcopy[0],x.size()); /* Eigen manual: Despite appearances, this does not invoke the memory allocator... */ } setdim(dim_); } /* Deep copy existing array - as above with dim_=x.dim */ template array(array &x):MapBase(NULL,0),vectorcopy(x){ if(x.size()>0){ new (this) MapBase(&vectorcopy[0],x.size()); /* Eigen manual: Despite appearances, this does not invoke the memory allocator... */ } setdim(x.dim); } /* Templated CTOR above may be ignored by the compiler. E.g. clang-13 used a compiler generated default copy CTOR which did not synchronize the MapBase::data() pointer (!) */ array(const array &x) : MapBase(NULL,0), vectorcopy(x) { if ( x.size() > 0 ) { // sync pointer new (this) MapBase(&vectorcopy[0], x.size()); } setdim(x.dim); } /* Sometimes we want a reference only... See col() */ array(Type *p, vector dim_):MapBase(p,dim_.prod()){ setdim(dim_); } /* Example: array a(3,4); array c=a; // Assign a.col(1)=c.col(1); // Assign array b=a.col(1); // Initialize (not this method) */ array & operator= (const array & other) { if(this->dim.size() == 0){ // Not initialized (default constructed) this->initZeroArray(other.dim); } this->MapBase::operator=(other); this->setdim(other.dim); return *this; } /* Assign array from any other object. First convert other object to 1D object (because we assign to underlying 1D array data). Example: a = m (assign from matrix) a.col(0) = m; (assign from matrix) a = m*m (assign from unevaluated expression template) a = v (assign from vector) */ template array operator=(T y){ Array a = y; a.resize(a.size(),1); return array(MapBase::operator=(a), dim); } void print(){ Rcout << "Array dim: "; for(int i=0;iMapBase::size();i++)Rcout << this->MapBase::operator[](i) << " "; Rcout << "\n"; }; /** \brief Number of outer-most dimensions \return Last array dimension (Similar to R's ncol in 2D case only) */ int cols(){ return dim[dim.size()-1]; } /** \brief Number of inner-most dimensions \return First array dimension (Similar to R's nrow) */ int rows(){ return dim[0]; } /** \brief Extract sub-array with write access Index i refers to the outer-most (i.e. final) dimension. */ array col(int i){ int nslice=this->MapBase::size()/this->cols(); Type* p=&(this->MapBase::operator()(i*nslice)); vector newdim; if(dim.size()>1){ newdim=dim.segment(0,dim.size()-1); } else { newdim.resize(1); newdim << 1; } return array(p,newdim); } /** \brief Elementwise subsetting 1D array. Also allowed in general to access the underlying vector of n-dim array. */ Type& operator()(int i1){ return this->MapBase::operator[](i1); } /** \brief Elementwise subsetting 2D array */ Type& operator()(int i1, int i2){ return this->MapBase::operator[](index(c(i1,i2))); } /** \brief Elementwise subsetting 3D array */ Type& operator()(int i1, int i2, int i3){ return this->MapBase::operator[](index(c(i1,i2,i3))); } /** \brief Elementwise subsetting 4D array */ Type& operator()(int i1, int i2, int i3, int i4){ return this->MapBase::operator[](index(c(i1,i2,i3,i4))); } /** \brief Elementwise subsetting 5D array */ Type& operator()(int i1, int i2, int i3, int i4, int i5){ return this->MapBase::operator[](index(c(i1,i2,i3,i4,i5))); } /** \brief Elementwise subsetting 6D array */ Type& operator()(int i1, int i2, int i3, int i4, int i5, int i6){ return this->MapBase::operator[](index(c(i1,i2,i3,i4,i5,i6))); } /** \brief Elementwise subsetting 7D array */ Type& operator()(int i1, int i2, int i3, int i4, int i5, int i6, int i7){ return this->MapBase::operator[](index(c(i1,i2,i3,i4,i5,i6,i7))); } int index(vector tup){ eigen_assert( tup.size() == dim.size() ); eigen_assert( ( (dim*0 <= tup) && (tup < dim) ).all() ); return (tup*mult).sum(); } vector tuple(int i){ vector revtup(dim.size()); vector revmult=mult.reverse(); for(int k=0;k perm(vector p){ vector x(this->size()); array ans(x,dim(p)); /* Create new array with permuted dimension */ for(int i=0;isize();i++){ /* Loop through values of old array */ ans[ans.index(tuple(i)(p))]=this->operator[](i); } return ans; } /** \brief Array transpose (Special case of array permutation) If e.g. x has dimension [3,4,5,6] then x.transpose() has dimension [6,5,4,3]. */ array transpose(){ vector p(dim.size()); for(int i=0;iperm(p.reverse()); } int mod(int i,int n){return ((i%n)+n)%n;} /** \brief Array rotate (Special case of array permutation) Rotates array dimension with n steps where n can be any (positive or negative) integer. If e.g. x has dimension [3,4,5,6] then x.rotate(1) has dimension [6,3,4,5]. */ array rotate(int n){ vector p(dim.size()); for(int i=0;iperm(p); } #define INHERIT(OP) \ template \ array OP(T y){return array(MapBase::OP(y),dim);} INHERIT(operator+) INHERIT(operator-) INHERIT(operator*) INHERIT(operator/) #undef INHERIT /** \brief Convert TMB array to matrix by keeping the first dimension and collapsing remaining dimensions. E.g. if array dimension is (n1,n2,n3) the resulting matrix dimension is (n1, n2*n3). */ tmbutils::matrix matrix(){ tmbutils::matrix ans = this->MapBase::matrix(); ans.resize(this->rows(), ans.size() / this->rows() ); return ans; } /** \brief Convert TMB array to vector */ tmbutils::vector vec() { return *this; } /* Methods this class should *not* inherit (generate compile time error if used) */ private: using MapBase::row; }; TMB/inst/include/tmbutils/supernodal_inverse_subset.hpp0000644000176200001440000002170614536067013023157 0ustar liggesusers#include #include namespace Eigen { /** \brief Supernodal Cholesky factor with access to protected members */ struct Accessible_CholmodSupernodalLLT : Eigen::CholmodSupernodalLLT > { typedef Eigen::CholmodSupernodalLLT > Base; // Inherit all CTORs using Base::Base; cholmod_factor* get_factor() { return m_cholmodFactor; } StorageIndex* get_super() { return static_cast(get_factor()->super); } StorageIndex* get_pi() { return static_cast(get_factor()->pi); } StorageIndex* get_s() { return static_cast(get_factor()->s); } StorageIndex* get_Perm() { return static_cast(get_factor()->Perm); } StorageIndex* get_px() { return static_cast(get_factor()->px); } size_t get_n() { return get_factor()->n; } size_t get_nsuper() { return get_factor()->nsuper; } size_t get_xsize() { return get_factor()->xsize; } double* get_x() { return static_cast(get_factor()->x); } }; template struct SupernodalInverseSubset { // typedefs typedef Accessible_CholmodSupernodalLLT Base; typedef Base::StorageIndex StorageIndex; typedef SparseMatrix SpMat; typedef Matrix Mat; typedef Map > Rows_ref; enum Operation { Get, Set, Update }; // workspaces std::shared_ptr chm; std::vector col2super; std::vector col2offset; std::vector idg; std::vector iwrk; std::vector ans; // Helper functions void init_col2super() { if (col2super.size() > 0) return; col2super.resize( chm->get_n() ); StorageIndex *super = chm->get_super(); Index nsuper = chm->get_nsuper(); for (Index k=0, l=0; k < nsuper; k++) { StorageIndex ncols = super[k + 1] - super[k]; while (ncols--) col2super[l++] = k; } } void init_col2offset() { if (col2offset.size() > 0) return; col2offset.resize( chm->get_n(), 0 ); StorageIndex *pi = chm->get_pi(); for (size_t i = 1; i < col2offset.size(); i++) { StorageIndex k = col2super[i - 1]; StorageIndex nrows = pi[k + 1] - pi[k]; col2offset[i] = col2offset[i - 1] + nrows; } } void chm_index_scatter(StorageIndex col, StorageIndex* wrk) { init_col2super(); init_col2offset(); StorageIndex k = col2super[col]; StorageIndex *pi = chm->get_pi(); StorageIndex *s = chm->get_s(); for (StorageIndex i = pi[k], j = col2offset[col] ; i < pi[k + 1] ; i++) { wrk[s[i]] = j++; } } std::vector index_gather(const SpMat &mat) { std::vector ans; StorageIndex *Perm = chm->get_Perm(); std::vector iPerm(mat.rows()); for (size_t i=0; i wrk(mat.rows()); for (StorageIndex k=0; k void values(SpMat &mat) { if (idg.size() == 0) idg = index_gather(mat); T* vptr = mat.valuePtr(); for (size_t i=0; iget_pi(); StorageIndex *s = chm->get_s(); StorageIndex nrows = pi[k + 1] - pi[k]; return Rows_ref(s + pi[k], nrows); } StorageIndex nrow(StorageIndex k) { StorageIndex *pi = chm->get_pi(); StorageIndex nrows = pi[k + 1] - pi[k]; return nrows; } StorageIndex ncol(StorageIndex k) { StorageIndex *super = chm->get_super(); StorageIndex ncols = super[k + 1] - super[k]; return ncols; } template void denseBlock(Mat &ans, T* x, StorageIndex* r, StorageIndex* c, StorageIndex nr, StorageIndex nc) { init_col2super(); if (iwrk.size() != chm->get_n()) iwrk.resize(chm->get_n()); // Super node specific information std::vector rel_rows; // rows relative to supernode StorageIndex i_start = 0; for (StorageIndex j = 0; j < nc; j++) { StorageIndex k = col2super[c[j]]; auto X = getSuperNode(x, k); StorageIndex *super = chm->get_super(); StorageIndex rel_col = c[j] - super[k]; // column relative to this supernode if (j == 0 || k != col2super[c[j-1]]) { // New supernode: Must update relative rows // Scatter relative supernode rows Rows_ref rows = rws(k); for (StorageIndex i=0; i getSuperNode(T* x, StorageIndex k) { StorageIndex *px = chm->get_px(); T* data = x + px[k]; Map ans(data, nrow(k), ncol(k)); return ans; } /* --- chol: get result from cholmod -------------------------------------- */ void chol_get_cached_values() { double* x = chm->get_x(); size_t n = chm->get_xsize(); ans.resize(n); for (size_t i=0; ix ans.resize(0); ans.resize(chm->get_xsize(), 0); // Fill SpMat into workspace values(x); // Forward loop StorageIndex *super = chm->get_super(); Index nsuper = chm->get_nsuper(); for (Index k=0; k < nsuper; k++) { Rows_ref rows = rws(k); // Notation StorageIndex ns = super[k + 1] - super[k]; StorageIndex np = rows.size() - ns; StorageIndex* p = rows.data() + ns; // r:=c(s,p) auto Xrs = getSuperNode(ans.data(), k); // Write access ! Xrs.block(0, 0, ns, ns) = Xrs.block(0, 0, ns, ns).llt().matrixL(); if (np > 0) { Mat Xpp(np, np); Xpp.setZero(); auto L = Xrs.block(0, 0, ns, ns); auto Xps = Xrs.block(ns, 0, np, ns); Xrs.block(ns, 0, np, ns) = L.template triangularView(). solve( Xps.transpose() ). transpose(); Xpp.template selfadjointView(). rankUpdate(Xrs.block(ns, 0, np, ns), -1.); denseBlock(Xpp, ans.data(), p, p, np, np); } } } /* --- chol2inv: reverse recursions --------------------------------------- */ void chol2inv() { // Reverse loop StorageIndex *super = chm->get_super(); Index nsuper = chm->get_nsuper(); for (Index k=nsuper; k > 0; ) { k--; Rows_ref rows = rws(k); // Notation StorageIndex ns = super[k + 1] - super[k]; StorageIndex np = rows.size() - ns; StorageIndex* p = rows.data() + ns; // r:=c(s,p) auto Xrs = getSuperNode(ans.data(), k); // Write access ! auto Lss = Xrs.block(0, 0, ns, ns); // Xss = chol2inv(Lss) Mat Lss_inv(ns, ns); Lss_inv.setIdentity(); Lss.template triangularView(). solveInPlace(Lss_inv); Xrs.block(0, 0, ns, ns).setZero(); Xrs.block(0, 0, ns, ns). template selfadjointView(). rankUpdate(Lss_inv.transpose(), 1.); if (np > 0) { Mat Xpp(np, np); denseBlock(Xpp, ans.data(), p, p, np, np); Mat Lps = Xrs.block(ns, 0, np, ns); Mat tmp = Lss_inv.template triangularView(). transpose() * Lps.transpose(); Xrs.block(ns, 0, np, ns) = (-tmp * Xpp.template selfadjointView()).transpose(); Xrs.block(0, 0, ns, ns) -= tmp * Xrs.block(ns, 0, np, ns); } } } SpMat operator()(SpMat x) { // forward recursions (use cached values if T=double) if (isDouble::value) { chol_get_cached_values(); } else { chol(x); } // Reverse chol2inv(); // Get result x = x * 0; values (x); return x; } SupernodalInverseSubset(std::shared_ptr chm) : chm(chm) { } void print_common() { cholmod_print_common("C", &(chm->cholmod())); } }; } // End namespace Eigen TMB/inst/include/tmbutils/newton.hpp0000644000176200001440000014322014536067013017171 0ustar liggesusers#ifdef TMBAD_FRAMEWORK /* =================== TODO =================== - Move entire code to TMBad ? - Option for saddlepoint solver ? - Generalize HessianSolveVector to handle non-symmetric jacobian - log_determinant of sparse matrix avoid branching issue ============================================ */ /** \brief Construct new sparse matrix of the *same pattern* as input \param S SparseMatrix with pattern \param x (optional) vector containing new nonzeros */ template Eigen::SparseMatrix pattern(const Eigen::SparseMatrix &S, std::vector x = std::vector(0) ) { if (S.nonZeros() > 0 && x.size() == 0) { x.resize(S.nonZeros()); } return Eigen::Map > (S.rows(), S.cols(), S.nonZeros(), S.outerIndexPtr(), S.innerIndexPtr(), x.data(), S.innerNonZeroPtr()); } #ifdef TMBAD_SUPERNODAL #include "supernodal_inverse_subset.hpp" #define INVERSE_SUBSET_TEMPLATE Eigen::SupernodalInverseSubset typedef Eigen::Accessible_CholmodSupernodalLLT DEFAULT_SPARSE_FACTORIZATION; inline double logDeterminant(const DEFAULT_SPARSE_FACTORIZATION &llt) { return llt.logDeterminant(); } #else #include "simplicial_inverse_subset.hpp" #define INVERSE_SUBSET_TEMPLATE Eigen::SimplicialInverseSubset typedef Eigen::SimplicialLLT > DEFAULT_SPARSE_FACTORIZATION; inline double logDeterminant(const DEFAULT_SPARSE_FACTORIZATION &llt) { return 2. * llt.matrixL().nestedExpression().diagonal().array().log().sum(); } #endif #include /** \brief Highly flexible atomic `Newton()` solver and `Laplace()` approximation ### Supported features - Several hessian structures: Sparse, dense and sparse plus lowrank. - Unlimited nesting (Newton solver within newton solver within ...) - AD to any order at runtime - AD Hessian of Laplace approximation (because inverse subset derivatives are implemented). - Sparse hessian of either simplicial or supernodal kind (via preprocessor flag `TMBAD_SUPERNODAL`). - CHOLMOD 64 bit integer versions for very large problems (from Eigen version 3.4). - Saddlepoint approximation */ namespace newton { // FIXME: R macro #ifdef eval #undef eval #endif template struct vector : Eigen::Array { typedef Type value_type; typedef Eigen::Array Base; vector(void) : Base() {} template vector(const Eigen::ArrayBase &x) : Base(x) {} template vector(const Eigen::MatrixBase &x) : Base(x) {} vector(size_t n) : Base(n) {} // std::vector operator std::vector() const { return std::vector (Base::data(), Base::data() + Base::size()); } vector(const std::vector &x) : Base(Eigen::Map (x.data(), x.size())) { } }; template struct matrix : Eigen::Matrix { typedef Eigen::Matrix Base; matrix(void) : Base() {} template matrix(const Eigen::ArrayBase &x) : Base(x) {} template matrix(const Eigen::MatrixBase &x) : Base(x) {} vector vec() const { Base a(*this); a.resize(a.size(), 1); return a; } }; /** \brief Operator (H, x) -> solve(H, x) Helper operator required to differentiate a newton solver. The matrix type `Hessian_Type` can be sparse or dense. */ template struct HessianSolveVector : TMBad::global::DynamicOperator< -1, -1 > { static const bool have_input_size_output_size = true; static const bool add_forward_replay_copy = true; std::shared_ptr hessian; size_t nnz, x_rows, x_cols; // Dim(x) HessianSolveVector(std::shared_ptr hessian, size_t x_cols = 1) : hessian ( hessian ), nnz ( hessian->Range() ), x_rows ( hessian->n ), x_cols ( x_cols ) {} TMBad::Index input_size() const { return nnz + x_rows * x_cols; } TMBad::Index output_size() const { return x_rows * x_cols; } vector solve(const vector &h, const vector &x) { typename Hessian_Type::template MatrixResult::type H = hessian -> as_matrix(h); hessian -> llt_factorize(H); // Assuming analyzePattern(H) has been called once matrix xm = x.matrix(); xm.resize(x_rows, x_cols); vector y = hessian -> llt_solve(H, xm).vec(); return y; } vector solve(const vector &h, const vector &x) { std::vector hx; hx.insert(hx.end(), h.data(), h.data() + h.size()); hx.insert(hx.end(), x.data(), x.data() + x.size()); TMBad::global::Complete Op(*this); std::vector ans = Op(hx); std::vector ans2(ans.begin(), ans.end()); return ans2; } void forward(TMBad::ForwardArgs &args) { size_t n = output_size(); vector h = args.x_segment(0, nnz), x = args.x_segment(nnz, n); args.y_segment(0, n) = solve(h, x); } template void reverse(TMBad::ReverseArgs &args) { size_t n = output_size(); vector h = args. x_segment(0, nnz), y = args. y_segment(0, n), dy = args.dy_segment(0, n); vector y2 = solve(h, dy); for (size_t j=0; j < x_cols; j++) { vector y_j = y .segment(j * x_rows, x_rows); vector y2_j = y2.segment(j * x_rows, x_rows); vector y2y_j = hessian -> crossprod(y2_j, y_j); args.dx_segment(0, nnz) -= y2y_j; args.dx_segment(nnz + j * x_rows, x_rows) += y2_j; } } template void forward(TMBad::ForwardArgs &args) { TMBAD_ASSERT(false); } void reverse(TMBad::ReverseArgs &args) { TMBAD_ASSERT(false); } const char* op_name() { return "JSolve"; } }; /* ======================================================================== */ /* === Matrix types that can be used by the Newton solver ================= */ /* ======================================================================== */ /* --- Dense Hessian ------------------------------------------------------ */ /** \brief Methods specific for a dense hessian */ template > > struct jacobian_dense_t : TMBad::ADFun<> { typedef TMBad::ADFun<> Base; template struct MatrixResult { typedef matrix type; }; size_t n; std::shared_ptr llt; jacobian_dense_t() {} // FIXME: Want const &F, &G, &H // --> JacFun, var2op, get_keep_var --> const jacobian_dense_t(TMBad::ADFun<> &H, size_t n) : n(n), llt(std::make_shared()) { Base::operator= ( H ); } jacobian_dense_t(TMBad::ADFun<> &F, TMBad::ADFun<> &G, size_t n) : n(n), llt(std::make_shared()) { std::vector keep_x(n, true); // inner keep_x.resize(G.Domain(), false); // outer std::vector keep_y(n, true); // inner Base::operator= ( G.JacFun(keep_x, keep_y) ); } template matrix as_matrix(const V &Hx) { typedef typename V::value_type T; return Eigen::Map > (Hx.data(), n, n); } template std::vector eval(const std::vector &x) { return Base::operator()(x); } template matrix operator()(const std::vector &x) { return as_matrix(Base::operator()(x)); } /** \brief Sparsity restricted cross product In dense case this is the usual cross product */ template vector crossprod(const vector &y2, const vector &y) { matrix ans = ( y2.matrix() * y.matrix().transpose() ).array(); return ans.vec(); } // Sparse.factorize() == Dense.compute() void llt_factorize(const matrix &h) { llt->compute(h); } Eigen::ComputationInfo llt_info() { return llt->info(); } /** \note Optional: This method allows the assumption that a prior call to `llt_factorize` has been performed for the same H */ matrix llt_solve(const matrix &H, const matrix &x) { return llt->solve(x); } template vector solve(std::shared_ptr ptr, const vector &h, const vector &x) { return HessianSolveVector(ptr).solve(h, x); } }; /* --- Sparse Hessian ----------------------------------------------------- */ /** \brief Methods specific for a sparse hessian */ template struct jacobian_sparse_t : TMBad::Sparse > { typedef TMBad::Sparse > Base; template struct MatrixResult { typedef Eigen::SparseMatrix type; }; size_t n; std::shared_ptr llt; jacobian_sparse_t& operator=(const jacobian_sparse_t &other) { Base::operator=(other); n = other.n; init_llt(); // llt.analyzePattern(H) return *this; } jacobian_sparse_t (const jacobian_sparse_t &other) : Base(other), n(other.n) { init_llt(); // llt.analyzePattern(H) } jacobian_sparse_t() {} void init_llt() { llt = std::make_shared(); // Analyze pattern std::vector dummy(this->Range(), 0); Eigen::SparseMatrix H_dummy = as_matrix(dummy); llt->analyzePattern(H_dummy); } // FIXME: &F, &G, &H const !!! jacobian_sparse_t(TMBad::Sparse > &H, size_t n) : n(n) { Base::operator= ( H ); init_llt(); // llt.analyzePattern(H) } jacobian_sparse_t(TMBad::ADFun<> &F, TMBad::ADFun<> &G, size_t n) : n(n) { std::vector keep_x(n, true); // inner keep_x.resize(G.Domain(), false); // outer std::vector keep_y(n, true); // inner Base::operator= (G.SpJacFun(keep_x, keep_y)); init_llt(); } // FIXME: Optimize sparsematrix CTOR by only doing 'setFromTriplets' once? template Eigen::SparseMatrix as_matrix(const V &Hx) { typedef typename V::value_type T; typedef Eigen::Triplet T3; std::vector tripletList(n); // Diagonal must always be part of pattern for(size_t i=0; i mat(n, n); mat.setFromTriplets(tripletList.begin(), tripletList.end()); return mat; } template std::vector eval(const std::vector &x) { return Base::operator()(x); } template Eigen::SparseMatrix operator()(const std::vector &x) { std::vector Hx = Base::operator()(x); return as_matrix(Hx); } /* Sparsity restricted cross product */ template vector crossprod(const vector &y2, const vector &y) { size_t nnz = Base::Range(); vector ans(nnz); for (size_t k=0; k &h) { llt->factorize(h); } Eigen::ComputationInfo llt_info() { return llt->info(); } /** \note Optional: This method allows the assumption that a prior call to `llt_factorize` has been performed for the same H */ matrix llt_solve(const Eigen::SparseMatrix &H, const matrix &x) { return llt->solve(x); } template vector solve(std::shared_ptr ptr, const vector &h, const vector &x) { return HessianSolveVector(ptr).solve(h, x); } }; /* --- Sparse Plus Low Rank Hessian --------------------------------------- */ /** \brief Operator to mark intermediate variables on the tape */ template struct TagOp : TMBad::global::Operator<1> { static const bool have_eval = true; static const bool add_forward_replay_copy = true; template Type eval(Type x0) { return x0 ; } template void reverse(TMBad::ReverseArgs &args) { args.dx(0) += args.dy(0); } const char* op_name() { return "TagOp"; } }; /** \brief Mark a variable during taping \details The 'sparse plus low rank' Hessian (`jacobian_sparse_plus_lowrank_t`) requires the user to manually mark variables used to identify the low rank contribution. For any intermediate variable `s(x)` we can write the objective function `f(x)` as `f(x,s(x))`. The hessian takes the form ``` hessian( f(x, s(x)) ) = jac(s)^T * f''_yy * jac(s) + R(x) ``` where the first term is referred to as a 'lowrank contribution' and `R(x)` is the remainder term. The user must choose `s(x)` in a way such that the remainder term becomes a sparse matrix. A good heuristic is (which you'll see by expanding the remainder term): - Choose `s(x)` that links to *many* random effects - Choose `s(x)` such that `hessian(s)` is sparse Example (incomplete) of use: \code PARAMETER_VECTOR(x); Type S = x.exp().sum(); // hessian(S) is sparse! S = Tag(S); // Mark S for lowrank contribution Type logS = log(S); // hessian(log(S)) is not sparse! return logS; \endcode */ TMBad::ad_plain Tag(const TMBad::ad_plain &x) CSKIP( { return TMBad::get_glob()->add_to_stack >(x); } ) /** \brief Otherwise ignore marks */ TMBad::Scalar Tag(const TMBad::Scalar &x) CSKIP( { return x; } ) /** \brief Methods specific for a sparse plus low rank hessian Represents a positive definite matrix of the form `H + G * H0 * G^T` where - H is sparse n-by-n (positive definite) - G is a dense n-by-k low rank matrix - H0 is dense k-by-k (preferably negative definite) To detect this structure one must use the `Tag()` function to select k intermediate variables which will be used to decompose the computational graph. Formulas ======== The following formulas are applied internally to perform the solve (Woodbury matrix identity) and determinant (Matrix determinant lemma). ## Solve ``` W = solve(H, G) M = solve(H0) + G^T * W solve(H + G * H0 * G^T) = solve(H) - W * solve(M) * W^T ``` ## determinant ``` det(H + G * H0 * G^T) = det(H) * det(H0) * det(M) ``` However, we use the substitution `H0M := H0 * M` for numerical robustness. These formulas are valid even when `H0 = 0`: ## Solve ``` W <- solve(H, G) H0M = I + H0 * t(G) * W solve(H + G * H0 * G^T) = solve(H) - W * solve(H0M) * H0 * t(W) ``` ## Determinant ``` det(H + G * H0 * G^T) = det(H) * det(H0M) ``` */ template struct jacobian_sparse_plus_lowrank_t { // The three tapes std::shared_ptr > H; std::shared_ptr > G; std::shared_ptr > H0; // ADFun methods that should apply to each of the three tapes void optimize() { H -> optimize(); G -> optimize(); H0 -> optimize(); } void DomainVecSet(const std::vector &x) { H -> DomainVecSet(x); G -> DomainVecSet(x); H0 -> DomainVecSet(x); } void SwapInner() { H -> SwapInner(); G -> SwapInner(); H0 -> SwapInner(); } void SwapOuter() { H -> SwapOuter(); G -> SwapOuter(); H0 -> SwapOuter(); } void print(TMBad::print_config cfg) { H -> print(cfg); G -> print(cfg); H0 -> print(cfg); } // Return type to represent the matrix template struct sparse_plus_lowrank { Eigen::SparseMatrix H; matrix G; matrix H0; // Optional: Store serialized representation of H vector Hvec; Eigen::Diagonal > diagonal() { return H.diagonal(); } }; template struct MatrixResult { typedef sparse_plus_lowrank type; }; size_t n; jacobian_sparse_plus_lowrank_t() {} jacobian_sparse_plus_lowrank_t(TMBad::ADFun<> &F, TMBad::ADFun<> &G_, size_t n) : n(n) { TMBad::Decomp2 > F2 = F.decompose("TagOp"); size_t k = F2.first.Range(); std::vector keep_rc(n, true); // inner keep_rc.resize(F.Domain(), false); // outer TMBad::Decomp3 > F3 = F2.HesFun(keep_rc, true, false, false); H = std::make_shared >(F3.first, n); G = std::make_shared >(F3.second); H0 = std::make_shared >(F3.third, k); } // unserialize template sparse_plus_lowrank as_matrix(const V &Hx) { typedef typename V::value_type T; const T* start = Hx.data(); std::vector v1(start, start + H -> Range()); start += H -> Range(); std::vector v2(start, start + G -> Range()); start += G -> Range(); std::vector v3(start, start + H0 -> Range()); sparse_plus_lowrank ans; ans.H = H -> as_matrix(v1); ans.Hvec = v1; ans.G = vector(v2); ans.G.resize(n, v2.size() / n); ans.H0 = H0 -> as_matrix(v3); return ans; } template std::vector eval(const std::vector &x) { std::vector ans = H -> eval(x); std::vector ans2 = (*G)(x); std::vector ans3 = H0 -> eval(x); ans.insert(ans.end(), ans2.begin(), ans2.end()); ans.insert(ans.end(), ans3.begin(), ans3.end()); return ans; } template sparse_plus_lowrank operator()(const std::vector &x) { return as_matrix(eval(x)); } void llt_factorize(const sparse_plus_lowrank &h) { H -> llt_factorize(h.H); } // FIXME: Diagonal increments should perhaps be applied to both H and H0. Eigen::ComputationInfo llt_info() { // Note: As long as diagonal increments are only applied to H this // is the relevant info: return H -> llt_info(); } /** \note Optional: This method allows the assumption that a prior call to `llt_factorize` has been performed for the same H */ matrix llt_solve(const sparse_plus_lowrank &h, const matrix &x) { matrix W = H -> llt_solve(h.H, h.G); // n x k matrix H0M = h.H0 * h.G.transpose() * W; H0M.diagonal().array() += TMBad::Scalar(1.); matrix y1 = H -> llt_solve(h.H, x); matrix y2 = W * H0M.ldlt().solve(h.H0 * W.transpose() * x); return y1 - y2; } template vector solve(std::shared_ptr > ptr, const vector &hvec, const vector &xvec) { using atomic::matmul; using atomic::matinv; sparse_plus_lowrank h = as_matrix(hvec); vector s = HessianSolveVector >(ptr -> H, h.G.cols()). solve(h.Hvec, h.G.vec()); tmbutils::matrix W = s.matrix(); W.resize(n, W.size() / n); tmbutils::matrix H0 = h.H0.array(); tmbutils::matrix Gt = h.G.transpose(); tmbutils::matrix H0M = matmul(H0, matmul(Gt, W)); H0M.diagonal().array() += T(1.); vector y1 = HessianSolveVector >(ptr -> H, 1). solve(h.Hvec, xvec); tmbutils::matrix iH0M = matinv(H0M); tmbutils::matrix Wt = W.transpose(); tmbutils::matrix xmat = xvec.matrix(); vector y2 = matmul(W, matmul(iH0M, matmul(H0, matmul(Wt, xmat)))).array(); return y1 - y2; } // Scalar case: A bit faster than the above template vector solve(const vector &h, const vector &x) { sparse_plus_lowrank H = as_matrix(h); llt_factorize(H); return llt_solve(H, x.matrix()).array(); } // Helper to get determinant: det(H)*det(H0)*det(M) template tmbutils::matrix getH0M(std::shared_ptr > ptr, const sparse_plus_lowrank &h) { vector s = HessianSolveVector >(ptr -> H, h.G.cols()). solve(h.Hvec, h.G.vec()); tmbutils::matrix W = s.matrix(); W.resize(n, W.size() / n); tmbutils::matrix H0 = h.H0.array(); tmbutils::matrix Gt = h.G.transpose(); tmbutils::matrix H0M = atomic::matmul(H0, atomic::matmul(Gt, W)); H0M.diagonal().array() += T(1.); return H0M; } }; /* ======================================================================== */ /* === Newton solver ====================================================== */ /* ======================================================================== */ /* --- Configuration ------------------------------------------------------ */ /** \brief Newton configuration parameters */ struct newton_config { /** \brief Max number of iterations */ int maxit; /** \brief Max number of allowed rejections */ int max_reject; /** \brief `max_reject` exceeded is convergence success **provided** that Hessian is PD? */ int ok_exit_if_pdhess; /** \brief Print trace info? */ int trace; /** \brief Convergence tolerance of max gradient component */ double grad_tol; /** \brief Convergence tolerance of consequtive function evaluations (not yet used) */ double step_tol; /** \brief Convergence tolerance of consequtive function evaluations (not yet used) */ double tol10; /** \brief Consider initial guess as invalid if the max gradient component is larger than this number */ double mgcmax; /** \brief Initial step size between 0 and 1 */ double ustep; /** \brief Internal parameter controlling ustep updates */ double power; /** \brief Internal parameter controlling ustep updates */ double u0; /** \brief Use *sparse* as opposed to dense hessian ? \details Using `sparse=true` for problem that is actually dense have been observed to results in a slowdown factor of approximately 3. In addition, the dense factorization can be accelerated using the `EIGEN_USE_MKL_ALL` preprocessor flag. On the other hand, using `sparse=false` (dense) for a problem that is actually sparse can result in much bigger slowdowns. */ bool sparse; /** \brief Detect an additional low rank contribution in sparse case? */ bool lowrank; bool decompose; /** \brief Detect and apply 'dead gradients' simplification */ bool simplify; /** \brief Behaviour on convergence failure: Report nan-solution ? */ bool on_failure_return_nan; /** \brief Behaviour on convergence failure: Throw warning ?*/ bool on_failure_give_warning; /** \brief Consider this absolute reduction 'significant' */ double signif_abs_reduction; /** \brief Consider this relative reduction 'significant' */ double signif_rel_reduction; /** \brief Modify Laplace approximation to return saddlepoint approximation? \details For this to work the inner objective function must return the negative log **MGF** rather than **density** */ bool SPA; void set_defaults(SEXP x = R_NilValue) { #define SET_DEFAULT(name, value) set_from_real(x, name, #name, value) SET_DEFAULT(maxit, 1000); SET_DEFAULT(max_reject, 10); SET_DEFAULT(ok_exit_if_pdhess, 1); SET_DEFAULT(trace, 0); SET_DEFAULT(grad_tol, 1e-8); SET_DEFAULT(step_tol, 1e-8); SET_DEFAULT(tol10, 0.001); SET_DEFAULT(mgcmax, 1e+60); SET_DEFAULT(ustep, 1); SET_DEFAULT(power, 0.5); SET_DEFAULT(u0, 1e-04); SET_DEFAULT(sparse, false); SET_DEFAULT(lowrank, false); SET_DEFAULT(decompose, true); SET_DEFAULT(simplify, true); SET_DEFAULT(on_failure_return_nan, true); SET_DEFAULT(on_failure_give_warning, true); SET_DEFAULT(signif_abs_reduction, 1e-6); SET_DEFAULT(signif_rel_reduction, .5); SET_DEFAULT(SPA, false); #undef SET_DEFAULT } newton_config() { set_defaults(); } newton_config(SEXP x) { set_defaults(x); } template void set_from_real(SEXP x, T &target, const char* name, double value) { SEXP y = getListElement(x, name); target = (T) ( y != R_NilValue ? REAL(y)[0] : value ); } }; template struct newton_config_t : newton_config { newton_config_t() : newton_config() {} newton_config_t(SEXP x) : newton_config(x) {} }; /* --- Newton Operator ---------------------------------------------------- */ /** \brief Generalized newton solver similar to TMB R function 'newton' \details This operator represents a Newton solver that can be put on the AD tape. Using the notation \f[ f(u,\theta) \f] for an objective function with 'inner' parameters \f$u\f$ and 'outer' parameters \f$\theta\f$, the operator is defined by \f[ \theta \rightarrow \hat{u}(\theta) := \text{argmin}_u f(u, \theta) \f]. ### Applied optimizations 1. If `cfg.decompose=true` (default), all sub-expressions of \f$f(u,\theta)\f$ that do *not* depend on \f$u\f$ are moved out of the solver, effecively corresponding to a re-parameterization of the outer parameters. An example could be that the objective function calculates a determinant that only depends on \f$\theta\f$. In this situation the result of the determinant becomes the new outer parameter rather than \f$\theta\f$. 2. A sligthly overlapping, but different, optimization is applied if `cfg.simplify=true` (default). We call it a 'dead gradient' analysis because it detects which \f$\theta_i\f$ do not affect the gradient of the objective wrt \f$u\f$. Such \f$\theta_i\f$ cannot affect the solution \f$\hat{u}\f$ either and can therefore be removed from the list of outer parameters, effectively reducing the input dimension of the Newton operator. \tparam Functor Class of the objective function. \tparam Hessian_Type Class of the hessian structure (sparse, dense or sparse_plus_lowrank). */ template > struct NewtonOperator : TMBad::global::DynamicOperator< -1, -1> { static const bool have_input_size_output_size = true; static const bool add_forward_replay_copy = true; typedef TMBad::Scalar Scalar; typedef TMBad::StdWrap > FunctorExtend; TMBad::ADFun<> function, gradient; std::shared_ptr hessian; // Control convergence newton_config cfg; // Outer parameters std::vector par_outer; /** \brief Constructor \param F Objective function taking `vector` as input and `TMBad::ad_aug` as output. \param start Initial guess for the optimizer. \param cfg Configuration parameters - see `newton_config`. */ NewtonOperator(Functor &F, vector start, newton_config cfg) : cfg(cfg) { // Create tape of the user functor and optimize the tape function = TMBad::ADFun<> ( FunctorExtend(F), start); function.optimize(); // The tape may contain expressions that do not depend on the // inner parameters (RefOp and expressions that only depend on // these). Move such expressions to the parent context? if (cfg.decompose) { function.decompose_refs(); } // The previous operation does not change the domain vector size. size_t n_inner = function.Domain(); TMBAD_ASSERT(n_inner == (size_t) start.size()); // Turn remaining references to parent contexts into outer // parameters. This operation increases function.Domain() par_outer = function.resolve_refs(); // Mark inner parameter subset in full parameter vector std::vector keep_inner(n_inner, true); keep_inner.resize(function.Domain(), false); // Gradient function gradient = function.JacFun(keep_inner); if (cfg.simplify) { // Masks std::vector active = gradient.activeDomain(); for (size_t i=0; i 0) { function.DomainReduce(active); gradient.DomainReduce(active); std::vector active_outer(active.begin() + n_inner, active.end()); par_outer = TMBad::subset(par_outer, active_outer); TMBAD_ASSERT(n_inner == (size_t) function.inner_inv_index.size()); function.optimize(); } } gradient.optimize(); // Hessian hessian = std::make_shared(function, gradient, n_inner); hessian -> optimize(); } // Helper to swap inner/outer void SwapInner() { function.SwapInner(); gradient.SwapInner(); hessian -> SwapInner(); } void SwapOuter() { function.SwapOuter(); gradient.SwapOuter(); hessian -> SwapOuter(); } // Put it self on tape vector add_to_tape() { TMBad::global::Complete solver(*this); std::vector sol = solver(par_outer); // Append outer paramaters to solution sol.insert(sol.end(), par_outer.begin(), par_outer.end()); return sol; } /* From TMB::newton */ double phi(double u) { return 1. / u - 1.; } double invphi(double x) { return 1. / (x + 1.); } double increase(double u) { return cfg.u0 + (1. - cfg.u0) * std::pow(u, cfg.power); } double decrease(double u) { return (u > 1e-10 ? 1. - increase(1. - u) : (1. - cfg.u0) * cfg.power * u); } vector x_start; // Cached initial guess const char* convergence_fail(const char* msg, vector &x) { if (cfg.on_failure_give_warning) { if (cfg.trace) { Rcout << "Newton convergence failure: " << msg << "\n"; } Rf_warning("Newton convergence failure: %s", msg); } if (cfg.on_failure_return_nan) { x.fill(NAN); } return msg; } const char* newton_iterate(vector &x) { int reject_counter = 0; const char* msg = NULL; Scalar f_x = function(x)[0]; if (x_start.size() == x.size()) { Scalar f_x_start = function(x_start)[0]; if ( ! std::isfinite(f_x_start) && ! std::isfinite(f_x) ) { return convergence_fail("Invalid initial guess", x); } if (f_x_start < f_x || ! std::isfinite(f_x)) { x = x_start; f_x = f_x_start; } } Scalar f_previous = f_x; if (cfg.trace) Rcout << "f_start=" << f_x << "\n"; for (int i=0; i < cfg.maxit; i++) { vector g = gradient(x); Scalar mgc = g.abs().maxCoeff(); if ( ! std::isfinite(mgc) || mgc > cfg.mgcmax) { return convergence_fail("Inner gradient had non-finite components", x); } /* FIXME: if (any(!is.finite(g))) stop("Newton dropout because inner gradient had non-finite components.") if (is.finite(mgcmax) && max(abs(g)) > mgcmax) stop("Newton dropout because inner gradient too steep.") if (max(abs(g)) < grad.tol) return(par) */ if (cfg.trace) Rcout << "mgc=" << mgc << " "; if (mgc < cfg.grad_tol) { x_start = x; if (cfg.trace) Rcout << "\n"; return msg; } typename Hessian_Type::template MatrixResult::type H = (*hessian)(std::vector(x)); vector diag_cpy = H.diagonal().array(); // Quick ustep reduction based on Hessian diagonal Scalar m = diag_cpy.minCoeff(); if (std::isfinite(m) && m < 0) { Scalar ustep_max = invphi(-m); cfg.ustep = std::min(cfg.ustep, ustep_max); } if (cfg.trace) Rcout << "ustep=" << cfg.ustep << " "; while (true) { // FIXME: Infinite loop // H := H + phi * I H.diagonal().array() = diag_cpy; H.diagonal().array() += phi( cfg.ustep ); // Try to factorize hessian -> llt_factorize(H); if (hessian -> llt_info() == 0) break; // H not PD ==> Decrease phi cfg.ustep = decrease(cfg.ustep); } // We now have a PD hessian // Let's take a newton step and see if it improves... vector x_new = x - hessian -> llt_solve(H, g).array(); Scalar f = function(x_new)[0]; // Accept/Reject rules bool accept = std::isfinite(f); if ( ! accept ) { reject_counter++; } else { // Accept if there's a value improvement: accept = (f < f_previous); // OR... if (! accept) { // Accept if relative mgc reduction is substantial without increasing value 'too much' accept = (f - f_previous <= cfg.signif_abs_reduction ) && vector(gradient(x_new)).abs().maxCoeff() / mgc < 1. - cfg.signif_rel_reduction; } // Assess the quality of the update if ( accept && (f_previous - f > cfg.signif_abs_reduction) ) { reject_counter = 0; } else { reject_counter++; } } // Take action depending on accept/reject if ( accept ) { // Improvement // Accept cfg.ustep = increase(cfg.ustep); f_previous = f; x = x_new; } else { // No improvement // Reject cfg.ustep = decrease(cfg.ustep); } // Handle long runs without improvement if (reject_counter > cfg.max_reject) { if (cfg.ok_exit_if_pdhess) { H = (*hessian)(std::vector(x)); // Try to factorize hessian -> llt_factorize(H); bool PD = (hessian -> llt_info() == 0); if (cfg.trace) Rcout << "Trying early exit - PD Hess? " << PD << "\n"; if (PD) return msg; } return convergence_fail("Max number of rejections exceeded", x); } // Tracing info if (cfg.trace) Rcout << "f=" << f << " "; if (cfg.trace) Rcout << "reject=" << reject_counter << " "; if (cfg.trace) Rcout << "\n"; } return convergence_fail("Iteration limit exceeded", x); } TMBad::Index input_size() const { return function.DomainOuter(); } TMBad::Index output_size() const { return function.DomainInner(); // Inner dimension } void forward(TMBad::ForwardArgs &args) { size_t n = function.DomainOuter(); std::vector x = args.x_segment(0, n); // Set *outer* parameters SwapOuter(); // swap function.DomainVecSet(x); gradient.DomainVecSet(x); hessian -> DomainVecSet(x); SwapOuter(); // swap back // Run *inner* iterations SwapInner(); // swap vector sol = function.DomainVec(); newton_iterate(sol); SwapInner(); // swap back args.y_segment(0, sol.size()) = sol; } template void reverse(TMBad::ReverseArgs &args) { vector w = args.dy_segment(0, output_size()); std::vector sol = args. y_segment(0, output_size()); // NOTE: 'hessian' must have full (inner, outer) vector as input size_t n = function.DomainOuter(); std::vector x = args.x_segment(0, n); std::vector sol_x = sol; sol_x.insert(sol_x.end(), x.begin(), x.end()); vector hv = hessian -> eval(sol_x); vector w2 = - hessian -> solve(hessian, hv, w); vector g = gradient.Jacobian(sol_x, w2); args.dx_segment(0, n) += g.tail(n); } template void forward(TMBad::ForwardArgs &args) { TMBAD_ASSERT(false); } void reverse(TMBad::ReverseArgs &args) { TMBAD_ASSERT(false); } const char* op_name() { return "Newton"; } void print(TMBad::global::print_config cfg) { Rcout << cfg.prefix << "======== function:\n"; function.print(cfg); Rcout << cfg.prefix << "======== gradient:\n"; gradient.print(cfg); Rcout << cfg.prefix << "======== hessian:\n"; hessian -> print(cfg); } }; typedef jacobian_sparse_t< DEFAULT_SPARSE_FACTORIZATION > jacobian_sparse_default_t; template struct InvSubOperator : TMBad::global::DynamicOperator< -1, -1> { static const bool have_input_size_output_size = true; static const bool add_forward_replay_copy = true; typedef TMBad::Scalar Scalar; Eigen::SparseMatrix hessian; // Pattern std::shared_ptr< Factorization > llt; // Factorization INVERSE_SUBSET_TEMPLATE ihessian; //typedef Eigen::AutoDiffScalar > ad1; typedef atomic::tiny_ad::variable<1,1> ad1; INVERSE_SUBSET_TEMPLATE D_ihessian; InvSubOperator(const Eigen::SparseMatrix &hessian, std::shared_ptr< Factorization > llt) : hessian(hessian), llt(llt), ihessian(llt), D_ihessian(llt) { } TMBad::Index input_size() const { return hessian.nonZeros(); } TMBad::Index output_size() const { return hessian.nonZeros(); } void forward(TMBad::ForwardArgs &args) { size_t n = input_size(); std::vector x = args.x_segment(0, n); Eigen::SparseMatrix h = pattern(hessian, x); llt->factorize(h); // Update shared factorization h = ihessian(h); args.y_segment(0, n) = h.valuePtr(); } void reverse(TMBad::ReverseArgs &args) { size_t n = input_size(); std::vector x = args. x_segment(0, n); std::vector dy = args.dy_segment(0, n); Eigen::SparseMatrix dy_mat = pattern(hessian, dy); // Symmetry correction (range direction) dy_mat.diagonal() *= 2.; dy_mat *= .5; std::vector x_ (n); for (size_t i=0; i h_ = pattern(hessian, x_); // Inverse subset h_ = D_ihessian(h_); // Symmetry correction h_.diagonal() *= .5; h_ *= 2.; // Gather result std::vector dx(n); for (size_t i=0; i void reverse(TMBad::ReverseArgs &args) { Rf_error("Inverse subset: order 2 not yet implemented (try changing config())"); } template void forward(TMBad::ForwardArgs &args) { TMBAD_ASSERT(false); } void reverse(TMBad::ReverseArgs &args) { TMBAD_ASSERT(false); } const char* op_name() { return "InvSub"; } }; template struct LogDetOperator : TMBad::global::DynamicOperator< -1, -1> { static const bool have_input_size_output_size = true; static const bool add_forward_replay_copy = true; typedef TMBad::Scalar Scalar; Eigen::SparseMatrix hessian; // Pattern std::shared_ptr< Factorization > llt; // Factorization INVERSE_SUBSET_TEMPLATE ihessian; LogDetOperator(const Eigen::SparseMatrix &hessian, std::shared_ptr< Factorization > llt) : hessian(hessian), llt(llt), ihessian(llt) { } TMBad::Index input_size() const { return hessian.nonZeros(); } TMBad::Index output_size() const { return 1; } void forward(TMBad::ForwardArgs &args) { size_t n = input_size(); std::vector x = args.x_segment(0, n); Eigen::SparseMatrix h = pattern(hessian, x); llt->factorize(h); // Get out if factorization went wrong if (llt->info() != 0) { args.y(0) = R_NaN; return; } args.y(0) = logDeterminant(*llt); } void reverse(TMBad::ReverseArgs &args) { size_t n = input_size(); // Get out if factorization went wrong if (llt->info() != 0) { for (size_t i=0; i x = args.x_segment(0, n); Eigen::SparseMatrix ih = pattern(hessian, x); // Inverse subset ih = ihessian(ih); // Symmetry correction ih.diagonal() *= .5; ih *= 2.; ih *= args.dy(0); args.dx_segment(0, n) += ih.valuePtr(); } void reverse(TMBad::ReverseArgs &args) { size_t n = input_size(); TMBad::global::Complete< InvSubOperator > IS(hessian, llt); std::vector x = args.x_segment(0, n); std::vector y = IS(x); Eigen::SparseMatrix ih = pattern(hessian, y); // Symmetry correction ih.diagonal() *= .5; ih *= 2.; ih *= args.dy(0); args.dx_segment(0, n) += ih.valuePtr(); } template void forward(TMBad::ForwardArgs &args) { TMBAD_ASSERT(false); } void reverse(TMBad::ReverseArgs &args) { TMBAD_ASSERT(false); } const char* op_name() { return "logDet"; } }; template Type log_determinant_simple(const Eigen::SparseMatrix &H) { // FIXME: Tape once for 'reasonable' numeric values - then replay // (to avoid unpredictable brancing issues) Eigen::SimplicialLDLT< Eigen::SparseMatrix > ldl(H); //return ldl.vectorD().log().sum(); vector D = ldl.vectorD(); return D.log().sum(); } template Type log_determinant(const Eigen::SparseMatrix &H, std::shared_ptr< jacobian_sparse_default_t > ptr) { if (!config.tmbad.atomic_sparse_log_determinant) return log_determinant_simple(H); const Type* vptr = H.valuePtr(); size_t n = H.nonZeros(); std::vector x(vptr, vptr + n); TMBad::global::Complete > LD(pattern(H), ptr->llt); std::vector y = LD(x); return y[0]; } template Type log_determinant(const Eigen::SparseMatrix &H) { const Type* vptr = H.valuePtr(); size_t n = H.nonZeros(); std::vector x(vptr, vptr + n); Eigen::SparseMatrix H_pattern = pattern(H); std::shared_ptr< DEFAULT_SPARSE_FACTORIZATION > llt = std::make_shared< DEFAULT_SPARSE_FACTORIZATION > (H_pattern); TMBad::global::Complete > LD(H_pattern, llt); std::vector y = LD(x); return y[0]; } inline double log_determinant(const Eigen::SparseMatrix &H) { DEFAULT_SPARSE_FACTORIZATION llt(H); return logDeterminant(llt); } inline double log_determinant(const Eigen::SparseMatrix &H, std::shared_ptr ptr) { // FIXME: Use ptr llt DEFAULT_SPARSE_FACTORIZATION llt(H); return logDeterminant(llt); } template Type log_determinant(const matrix &H, PTR ptr) { // FIXME: Depending on TMB atomic return atomic::logdet(tmbutils::matrix(H)); } template Type log_determinant(const jacobian_sparse_plus_lowrank_t<>::sparse_plus_lowrank &H, std::shared_ptr > ptr) { matrix H0M = (ptr -> getH0M(ptr, H)).array(); return log_determinant(H.H, ptr->H) + log_determinant(H0M, NULL); } // Interface template void Newton_CTOR_Hook(Newton &F, const vector &start) { F.sol = start; F.newton_iterate(F.sol); } template void Newton_CTOR_Hook(Newton &F, const vector &start) { F.sol = F.add_to_tape(); } /** Helper to simplify user interface of Functor by making `ad_aug` version work for `double` as well In principle, the double case should be trivial, as it evaluates the functor using AD types that are constants. However, some operators might add to tape for constant inputs (by mistake). To guard aginst such mistakes, we wrap the double evaluation inside a dummy AD context. */ template struct safe_eval { Type operator()(Functor &F, vector x) { return F(x); } }; template struct safe_eval { double operator()(Functor &F, vector x) { /* double case: Wrap evaluation inside an AD context, just in case some operations in F adds to tape. */ TMBad::global dummy; dummy.ad_start(); double ans = asDouble(F(x)); dummy.ad_stop(); return ans; } }; template > struct NewtonSolver : NewtonOperator { typedef NewtonOperator Base; typedef typename Hessian_Type::template MatrixResult::type hessian_t; vector sol; // c(sol, par_outer) size_t n; // Number of inner parameters Functor& F; NewtonSolver(Functor &F, vector start, newton_config cfg) : Base(F, start, cfg), n(start.size()), F(F) { Newton_CTOR_Hook(*this, start); } // Get solution operator vector() const { return sol.head(n); } tmbutils::vector solution() { return sol.head(n); } Type value() { if (Base::cfg.simplify) { return safe_eval()(F, solution()); } else { return Base::function(std::vector(sol))[0]; } } hessian_t hessian() { return (*(Base::hessian))(std::vector(sol)); } Type Laplace() { double sign = (Base::cfg.SPA ? -1 : 1); return sign * value() + .5 * log_determinant( hessian(), Base::hessian) - sign * .5 * log(2. * M_PI) * n; } }; template NewtonSolver > NewtonSparse( Functor &F, Eigen::Array start, newton_config cfg = newton_config() ) { NewtonSolver > ans(F, start, cfg); return ans; } template NewtonSolver > NewtonDense( Functor &F, Eigen::Array start, newton_config cfg = newton_config() ) { NewtonSolver > ans(F, start, cfg); return ans; } template NewtonSolver > NewtonSparsePlusLowrank( Functor &F, Eigen::Array start, newton_config cfg = newton_config() ) { NewtonSolver > ans(F, start, cfg); return ans; } /** \brief Tape a functor and return solution Can be used anywhere in a template. Inner and outer parameters are automatically detected. \param F Function to minimize \param start Vector with initial guess \param cfg Configuration parameters for solver \return Vector with solution */ template vector Newton(Functor &F, Eigen::Array start, newton_config cfg = newton_config() ) { if (cfg.sparse) { if (! cfg.lowrank) return NewtonSparse(F, start, cfg); else return NewtonSparsePlusLowrank(F, start, cfg); } else return NewtonDense(F, start, cfg); } /** \brief Tape a functor and return Laplace Approximation Can be used anywhere in a template. Inner and outer parameters are automatically detected. \param F Function to minimize \param start Vector with initial guess \param cfg Configuration parameters for solver \return Scalar with Laplace Approximation \note `start` is passed by reference and contains the inner problem mode on output */ template Type Laplace(Functor &F, Eigen::Array &start, newton_config cfg = newton_config() ) { if (cfg.sparse) { if (!cfg.lowrank) { auto opt = NewtonSparse(F, start, cfg); start = opt.solution(); return opt.Laplace(); } else { auto opt = NewtonSparsePlusLowrank(F, start, cfg); start = opt.solution(); return opt.Laplace(); } } else { auto opt = NewtonDense(F, start, cfg); start = opt.solution(); return opt.Laplace(); } } // Usage: slice<>(F, random).Laplace(cfg); template > struct slice { ADFun &F; std::vector random; slice(ADFun &F, //std::vector x, std::vector random) : F(F), random(random) { TMBAD_ASSERT2(F.Range() == 1, "Laplace approximation is for scalar valued functions"); } typedef TMBad::ad_aug T; std::vector x; T operator()(const std::vector &x_random) { for (size_t i=0; i xd = F.DomainVec(); x = std::vector (xd.begin(), xd.end()); ans.glob.ad_start(); TMBad::Independent(x); vector start = TMBad::subset(x, random); T y = Laplace(*this, start, cfg); y.Dependent(); ans.glob.ad_stop(); return ans; } }; TMBad::ADFun<> Laplace_(TMBad::ADFun<> &F, const std::vector &random, newton_config cfg = newton_config() ) CSKIP( { slice<> S(F, random); return S.Laplace_(cfg); } ) } // End namespace newton #endif // TMBAD_FRAMEWORK TMB/inst/include/tmbutils/splines.hpp0000644000176200001440000003077514536067013017346 0ustar liggesusers/** \file \brief R's spline function wrapped into template class that can be used with TMB. */ namespace tmbutils { // Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /* * R : A Computer Language for Statistical Data Analysis * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka * Copyright (C) 1998--2001 Robert Gentleman, Ross Ihaka and the * R Development Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, a copy is available at * http://www.r-project.org/Licenses/ */ /* Spline Interpolation * -------------------- * C code to perform spline fitting and interpolation. * There is code here for: * * 1. Natural splines. * * 2. Periodic splines * * 3. Splines with end-conditions determined by fitting * cubics in the start and end intervals (Forsythe et al). * * * Computational Techniques * ------------------------ * A special LU decomposition for symmetric tridiagonal matrices * is used for all computations, except for periodic splines where * Choleski is more efficient. */ /** \brief Spline Interpolation R's spline function wrapped into template class that can be used with TMB. \warning Spline evaluation involves branching on the x-values and may thus be problematic for parameter dependent inputs. */ template class splinefun { private: /* Input to R's "spline_coef" */ int method[1]; int n[1]; Type *x; Type *y; Type *b; Type *c; Type *d; Type *e; /* Not used */ //int errno, EDOM; /* Memory management helpers */ void clear() { if (*n != 0) { delete [] x; delete [] y; delete [] b; delete [] c; delete [] d; delete [] e; } } void alloc(int n_) { *n = n_; x = new Type[*n]; y = new Type[*n]; b = new Type[*n]; c = new Type[*n]; d = new Type[*n]; e = new Type[*n]; } void copy_from(const splinefun &fun) { *method = fun.method[0]; *n = fun.n[0]; alloc(*n); for(int i = 0; i < *n; i++) { x[i] = fun.x[i]; y[i] = fun.y[i]; b[i] = fun.b[i]; c[i] = fun.c[i]; d[i] = fun.d[i]; e[i] = fun.e[i]; } } public: /* Construct spline */ splinefun() { x = y = b = c = d = e = NULL; *method = *n = 0; }; splinefun(const splinefun &fun){ copy_from(fun); } splinefun& operator=(const splinefun &x) { if (this != &x) { (*this).clear(); (*this).copy_from(x); } return *this; } ~splinefun() { clear(); }; /** \brief Construct spline function object \param x_ x values values \param y_ y values - same length as x. \param method Integer determining the spline type: 1. Natural splines. 2. Periodic splines 3. Splines with end-conditions determined by fitting cubics in the start and end intervals (Forsythe et al). */ splinefun(const vector &x_, const vector &y_, int method_ = 3) { method[0] = method_; n[0] = x_.size(); alloc( x_.size() ); for(int i=0; i < *n; i++) { x[i] = x_[i]; y[i] = y_[i]; } spline_coef(method, n, x, y, b, c, d, e); } /** \brief Evaluate spline - scalar argument case */ Type operator()(const Type &x_) { Type u[1]; Type v[1]; int nu[1]; u[0] = x_; nu[0] = 1; spline_eval(method, nu, u, v, n, x, y, b, c, d); return v[0]; } /** \brief Evaluate spline - vector argument case */ vector operator() (const vector &x) { vector y(x.size()); for (int i=0; i1 ; i--) c[i] = (c[i]-d[i]*c[i+1])/b[i]; /* End conditions */ c[1] = c[n] = 0.0; /* Get cubic coefficients */ b[1] = (y[2] - y[1])/d[1] - d[i] * c[2]; c[1] = 0.0; d[1] = c[2]/d[1]; b[n] = (y[n] - y[nm1])/d[nm1] + d[nm1] * c[nm1]; for(i=2 ; i 3) { c[1] = c[3]/(x[4]-x[2]) - c[2]/(x[3]-x[1]); c[n] = c[nm1]/(x[n] - x[n-2]) - c[n-2]/(x[nm1]-x[n-3]); c[1] = c[1]*d[1]*d[1]/(x[4]-x[1]); c[n] = -c[n]*d[nm1]*d[nm1]/(x[n]-x[n-3]); } /* Gaussian elimination */ for(i=2 ; i<=n ; i++) { t = d[i-1]/b[i-1]; b[i] = b[i] - t*d[i-1]; c[i] = c[i] - t*c[i-1]; } /* Backward substitution */ c[n] = c[n]/b[n]; for(i=nm1 ; i>=1 ; i--) c[i] = (c[i]-d[i]*c[i+1])/b[i]; /* c[i] is now the sigma[i-1] of the text */ /* Compute polynomial coefficients */ b[n] = (y[n] - y[n-1])/d[n-1] + d[n-1]*(c[n-1]+ 2.0*c[n]); for(i=1 ; i<=nm1 ; i++) { b[i] = (y[i+1]-y[i])/d[i] - d[i]*(c[i+1]+2.0*c[i]); d[i] = (c[i+1]-c[i])/d[i]; c[i] = 3.0*c[i]; } c[n] = 3.0*c[n]; d[n] = d[nm1]; return; } /* * Periodic Spline * --------------- * The end conditions here match spline (and its derivatives) * at x[1] and x[n]. * * Note: There is an explicit check that the user has supplied * data with y[1] equal to y[n]. */ void periodic_spline(int n, Type *x, Type *y, Type *b, Type *c, Type *d, Type *e) { Type s; int i, nm1; /* Adjustment for 1-based arrays */ x--; y--; b--; c--; d--; e--; if(n < 2 || y[1] != y[n]) { errno = EDOM; return; } if(n == 2) { b[1] = b[2] = c[1] = c[2] = d[1] = d[2] = 0.0; return; } else if (n == 3) { b[1] = b[2] = b[3] = -(y[1] - y[2])*(x[1] - 2*x[2] + x[3])/(x[3]-x[2])/(x[2]-x[1]); c[1] = -3*(y[1]-y[2])/(x[3]-x[2])/(x[2]-x[1]); c[2] = -c[1]; c[3] = c[1]; d[1] = -2*c[1]/3/(x[2]-x[1]); d[2] = -d[1]*(x[2]-x[1])/(x[3]-x[2]); d[3] = d[1]; return; } /* else --------- n >= 4 --------- */ nm1 = n-1; /* Set up the matrix system */ /* A = diagonal B = off-diagonal C = rhs */ #define A b #define B d #define C c B[1] = x[2] - x[1]; B[nm1]= x[n] - x[nm1]; A[1] = 2.0 * (B[1] + B[nm1]); C[1] = (y[2] - y[1])/B[1] - (y[n] - y[nm1])/B[nm1]; for(i = 2; i < n; i++) { B[i] = x[i+1] - x[i]; A[i] = 2.0 * (B[i] + B[i-1]); C[i] = (y[i+1] - y[i])/B[i] - (y[i] - y[i-1])/B[i-1]; } /* Choleski decomposition */ #define L b #define M d #define E e L[1] = sqrt(A[1]); E[1] = (x[n] - x[nm1])/L[1]; s = 0.0; for(i = 1; i <= nm1 - 2; i++) { M[i] = B[i]/L[i]; if(i != 1) E[i] = -E[i-1] * M[i-1] / L[i]; L[i+1] = sqrt(A[i+1]-M[i]*M[i]); s = s + E[i] * E[i]; } M[nm1-1] = (B[nm1-1] - E[nm1-2] * M[nm1-2])/L[nm1-1]; L[nm1] = sqrt(A[nm1] - M[nm1-1]*M[nm1-1] - s); /* Forward Elimination */ #define Y c #define D c Y[1] = D[1]/L[1]; s = 0.0; for(i=2 ; i<=nm1-1 ; i++) { Y[i] = (D[i] - M[i-1]*Y[i-1])/L[i]; s = s + E[i-1] * Y[i-1]; } Y[nm1] = (D[nm1] - M[nm1-1] * Y[nm1-1] - s) / L[nm1]; #define X c X[nm1] = Y[nm1]/L[nm1]; X[nm1-1] = (Y[nm1-1] - M[nm1-1] * X[nm1])/L[nm1-1]; for(i=nm1-2 ; i>=1 ; i--) X[i] = (Y[i] - M[i] * X[i+1] - E[i] * X[nm1])/L[i]; /* Wrap around */ X[n] = X[1]; /* Compute polynomial coefficients */ for(i=1 ; i<=nm1 ; i++) { s = x[i+1] - x[i]; b[i] = (y[i+1]-y[i])/s - s*(c[i+1]+2.0*c[i]); d[i] = (c[i+1]-c[i])/s; c[i] = 3.0*c[i]; } b[n] = b[1]; c[n] = c[1]; d[n] = d[1]; return; } #undef A #undef B #undef C #undef L #undef M #undef E #undef Y #undef D #undef X void spline_coef(int *method, int *n, Type *x, Type *y, Type *b, Type *c, Type *d, Type *e) { switch(*method) { case 1: periodic_spline(*n, x, y, b, c, d, e); break; case 2: natural_spline(*n, x, y, b, c, d); break; case 3: fmm_spline(*n, x, y, b, c, d); break; } } void spline_eval(int *method, int *nu, Type *u, Type *v, int *n, Type *x, Type *y, Type *b, Type *c, Type *d) { /* Evaluate v[l] := spline(u[l], ...), l = 1,..,nu, i.e. 0:(nu-1) * Nodes x[i], coef (y[i]; b[i],c[i],d[i]); i = 1,..,n , i.e. 0:(*n-1) */ const int n_1 = *n - 1; int i, j, k, l; Type ul, dx, tmp; if(*method == 1 && *n > 1) { /* periodic */ dx = x[n_1] - x[0]; for(l = 0; l < *nu; l++) { /* WARNING - "fmod(AD,AD)" is not defined */ v[l] = fmod(asDouble(u[l]-x[0]), asDouble(dx)); if(v[l] < 0.0) v[l] += dx; v[l] += x[0]; } } else { for(l = 0; l < *nu; l++) v[l] = u[l]; } i = 0; for(l = 0; l < *nu; l++) { ul = v[l]; if(ul < x[i] || (i < n_1 && x[i+1] < ul)) { /* reset i such that x[i] <= ul <= x[i+1] : */ i = 0; j = *n; do { k = (i+j)/2; if(ul < x[k]) j = k; else i = k; } while(j > i+1); } dx = ul - x[i]; /* for natural splines extrapolate linearly left */ tmp = (*method == 2 && ul < x[0]) ? 0.0 : d[i]; v[l] = y[i] + dx*(b[i] + dx*(c[i] + dx*tmp)); } } }; } TMB/inst/include/tmbutils/R_inla.hpp0000644000176200001440000001176714536067013017075 0ustar liggesusers// Copyright (C) 2015 Hans Skaug // License: GPL-2 /** \file R_inla.hpp Makes SPDE methods from INLA R-package available in TMB. */ /** \brief SPDE methods from INLA R-package . Constructs precission matrix Q of the type defined in Lindgren et al. (2011). Requires RINLA package to build stuff. Q built this way can be used in \ref GMRF_t. */ namespace R_inla { using namespace Eigen; using namespace tmbutils; /** \brief Object containing all elements of an SPDE object, i.e. eqn (10) in Lindgren et al. */ template struct spde_t{ SparseMatrix M0; // G0 eqn (10) in Lindgren SparseMatrix M1; // G1 eqn (10) in Lindgren SparseMatrix M2; // G2 eqn (10) in Lindgren spde_t(SEXP x){ /* x = List passed from R */ M0 = asSparseMatrix(getListElement(x,"M0")); M1 = asSparseMatrix(getListElement(x,"M1")); M2 = asSparseMatrix(getListElement(x,"M2")); } }; /** Precision matrix eqn (10) in Lindgren et al. (2011) */ template SparseMatrix Q_spde(spde_t spde, Type kappa){ Type kappa_pow2 = kappa*kappa; Type kappa_pow4 = kappa_pow2*kappa_pow2; return kappa_pow4*spde.M0 + Type(2.0)*kappa_pow2*spde.M1 + spde.M2; // M0=G0, M1=G1, M2=G2 } /** \brief Object containing all elements of an anisotropic SPDE object, i.e. eqn (20) in Lindgren et al. */ template struct spde_aniso_t{ int n_s; int n_tri; vector Tri_Area; matrix E0; matrix E1; matrix E2; matrix TV; SparseMatrix G0; SparseMatrix G0_inv; spde_aniso_t(SEXP x){ /* x = List passed from R */ n_s = CppAD::Integer(asVector(getListElement(x,"n_s"))[0]); n_tri = CppAD::Integer(asVector(getListElement(x,"n_tri"))[0]); Tri_Area = asVector(getListElement(x,"Tri_Area")); E0 = asMatrix(getListElement(x,"E0")); E1 = asMatrix(getListElement(x,"E1")); E2 = asMatrix(getListElement(x,"E2")); TV = asMatrix(getListElement(x,"TV")); G0 = asSparseMatrix(getListElement(x,"G0")); G0_inv = asSparseMatrix(getListElement(x,"G0_inv")); } }; /** Precision matrix for the anisotropic case, eqn (20) in Lindgren et al. (2011) */ template SparseMatrix Q_spde(spde_aniso_t spde, Type kappa, matrix H){ int i; Type kappa_pow2 = kappa*kappa; Type kappa_pow4 = kappa_pow2*kappa_pow2; int n_s = spde.n_s; int n_tri = spde.n_tri; vector Tri_Area = spde.Tri_Area; matrix E0 = spde.E0; matrix E1 = spde.E1; matrix E2 = spde.E2; matrix TV = spde.TV; SparseMatrix G0 = spde.G0; SparseMatrix G0_inv = spde.G0_inv; //Type H_trace = H(0,0)+H(1,1); //Type H_det = H(0,0)*H(1,1)-H(0,1)*H(1,0); SparseMatrix G1_aniso(n_s,n_s); SparseMatrix G2_aniso(n_s,n_s); // Calculate adjugate of H matrix adj_H(2,2); adj_H(0,0) = H(1,1); adj_H(0,1) = -1 * H(0,1); adj_H(1,0) = -1 * H(1,0); adj_H(1,1) = H(0,0); // Calculate new SPDE matrices // Calculate G1 - pt. 1 array Gtmp(n_tri,3,3); for(i=0; i struct vector : Array { typedef Type value_type; typedef Array Base; vector(void):Base() {} template vector(T1 x):Base(x) {} template vector(T1 x, T2 y):Base(x,y) {} template vector & operator= (const T1 & other) { this->Base::operator=(other); return *this; } // /* index-vector subset */ // template // Type & operator()(T ind){ // return this->Base::operator()(ind); // } using Base::operator(); // kasper: would be better with references, i.e. allow x(indvec)=y; vector operator()(vector ind){ vector ans(ind.size()); for(int i=0;ioperator[](ind[i]); return ans; } /* Convert to _other_ vector class Examples 1. vector to CppAD::vector 2. vector to CppAD::vector */ template operator CppAD::vector(){ int n = this->size(); CppAD::vector x(n); for(int i=0; ioperator[](i)); return x; } /* Convert to _this_ vector class Examples: 2. CppAD::vector to vector 3. CppAD::vector to vector FIXME: Which one takes care of: vector to vector ? */ template vector(CppAD::vector x):Base(){ int n = x.size(); this->resize(n); for(int i=0; ioperator[](i) = Type(x[i]); } // std::vector operator std::vector(){ int n = this->size(); std::vector x(n); for(int i=0; i &x) : Base(){ int n = x.size(); this->resize(n); for(int i=0; i vec() { return *this; } }; /** \brief Matrix class used by TMB. The TMB matrix class is implemented as an Eigen Matrix of dynamic dimension. In particular, linear algebra methods are inherited from the Eigen library. */ template struct matrix : Matrix { typedef Matrix Base; matrix(void):Base() {} template matrix(T1 x):Base(x) {} template matrix(T1 x, T2 y):Base(x,y) {} template matrix & operator= (const T1 & other) { this->Base::operator=(other); return *this; } /** The vec operator stacks the matrix columns into a single vector. */ vector vec(){ Array a = this->array(); a.resize(a.size(), 1); return a; } }; TMB/inst/include/tmbutils/tmbutils.hpp0000644000176200001440000000170614536067013017524 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file \brief Namespace of utility functions for TMB */ /** \brief Utility functions for TMB (automatically included) Contains basic data types such as vectors, matrices and arrays. Included automatically so you \b should \b NOT include it via \code using tmbutils \endcode */ namespace tmbutils{ // Utilities used by the core using namespace Eigen; #include "vector.hpp" #include "array.hpp" template vector asVector(From *px, int n){ vector x(n); for(int i=0;i array asArray(SEXP x) { if(!Rf_isArray(x))Rf_error("NOT AN ARRAY!"); SEXP dim=Rf_getAttrib(x,R_DimSymbol); vector d=asVector(INTEGER(dim), LENGTH(dim)); vector y=asVector(REAL(x), LENGTH(x)); return array(y,d); } #endif } // End namespace TMB/inst/include/tmbutils/simplicial_inverse_subset.hpp0000644000176200001440000001175414536067013023133 0ustar liggesusersnamespace Eigen { template struct SimplicialInverseSubset { // typedefs typedef SimplicialLLT > Base; typedef SimplicialLLT > BaseD; typedef typename Base::StorageIndex StorageIndex; typedef typename Base::Scalar Scalar; typedef SparseMatrix SpMat; enum Operation { //IndexScatter, Scatter, Zero, InnerProduct }; // workspaces std::shared_ptr factor; std::vector idg; std::vector index_gather(const SpMat &mat) { SpMat L = factor->matrixL(); const StorageIndex* Lp = L.outerIndexPtr(); const StorageIndex* Li = L.innerIndexPtr(); std::vector ans; const StorageIndex *Perm = factor->permutationP().indices().data(); std::vector wrk(mat.rows()); for (StorageIndex k=0; k Scalar column(SparseMatrix &L, StorageIndex j, Scalar* x) { const StorageIndex* Lp = L.outerIndexPtr(); const StorageIndex* Li = L.innerIndexPtr(); Scalar_* Lx = L.valuePtr(); Scalar s = 0; for (StorageIndex k=Lp[j]; k LT; void init_transpose(SpMat L) { if (LT.rows() > 0) return; std::vector x(L.nonZeros()); for (size_t i=0; i TMP = Eigen::Map > (L.rows(), L.cols(), L.nonZeros(), L.outerIndexPtr(), L.innerIndexPtr(), x.data(), L.innerNonZeroPtr()); LT = TMP.transpose(); } SpMat chol2inv() { SpMat L = factor->matrixL(); init_transpose(L); // Allocate result SpMat S(L); for (StorageIndex i=0; i wrk(ncol, 0); T* S_row = wrk.data(); // Recursions for (StorageIndex j = ncol; j > 0; ) { j--; // Scatter sub-column S(j:n,j) column (S, j, S_row); // Diagonal element S(j,j) Scalar Sjj = 0; for (StorageIndex k = Lp[j] + 1; k < Lp[j+1]; k++) { Sjj += Lx[k] * Sx[k]; } Scalar Ljj_inv = 1. / Lx[Lp[j]]; S_row[j] = -Ljj_inv * Sjj + Ljj_inv * Ljj_inv; // Recursions for j'th row S(j,1:(j-1)) for (StorageIndex k = LTp[j+1]-1; k > LTp[j]; ) { k--; StorageIndex i = LTi[k]; S_row[i] = (-1. / Lx[Lp[i]]) * column (L, i, S_row); } for (StorageIndex k = LTp[j]; k < LTp[j+1]; k++) { // Insert result in sparse output StorageIndex i = LTi[k]; StorageIndex kT = LTx[k]; Sx[kT] = S_row[i]; } // Clear workspace column (L, j, S_row); column (LT, j, S_row); } return S; } SpMat operator()(SpMat x) { // Factor initialize if (!factor) { factor = std::make_shared(x); } // forward recursions factor->factorize(x); // Reverse SpMat S = chol2inv(); // Get result x = x * 0; valuesGet (x, S); return x; } // No simple way to change factor to other numerical type // SimplicialInverseSubset(std::shared_ptr factor) : // factor(factor) { } SimplicialInverseSubset(std::shared_ptr factor) { } }; } // Eigen TMB/inst/include/tmbutils/concat.hpp0000644000176200001440000000523114536067013017125 0ustar liggesusers/** \file \brief Object concatenation. */ namespace tmbutils { template struct concat_traits { typedef T value_type; T* ptr(T &x) { return &x; } size_t size(T &x) { return 1; } }; template struct concat_traits_vector { typedef typename VT::value_type value_type; typedef value_type T; T* ptr(VT &x) { return x.data(); } size_t size(VT &x) { return x.size(); } }; template struct concat_traits > : concat_traits_vector > {}; template struct concat_traits > : concat_traits_vector > {}; template struct concat_traits > : concat_traits_vector > {}; /** \brief Serialized representation of objects of different types */ template struct Concat { S& cur; Concat next; typedef typename concat_traits::value_type value_type; void assign_from(const value_type* x) { value_type* dest = concat_traits().ptr(cur); size_t n = concat_traits().size(cur); for (size_t i=0; i().ptr(cur); size_t n = concat_traits().size(cur); for (size_t i=0; i().size(cur) + next.size(); } operator vector() { vector ans(size()); assign_to(ans.data()); return ans; } Concat& operator=(const vector &x) { assign_from(x.data()); return *this; } }; template<> struct Concat { template void assign_from(T x) { } template void assign_to(T x) { } size_t size() { return 0; } }; /** \brief Serialized representation of objects of different types \details This function provides an interface between a parameter list and its serialized (vector) representation. In R, this would correspond to 'unlist()/relist()'. Example: \code // Custom parameter list template struct parameter_list { vector v; matrix m; array a; Type s; // To enable unlist/relist functionality, we must specify which members to include in representation: auto unlist() { return concat(v, m, a, s); } }; // Declare a parameter list parameter_list pl; // To 'unlist' it do vector parms = pl.unlist(); // To 'relist' it do pl.unlist() = parms; \endcode \note Return type 'auto' requires C++14. */ template Concat concat(Ts&... args) { return Concat({args...}); } } // End namespace TMB/inst/include/tmbutils/tmbutils_extra.hpp0000644000176200001440000000112214536067013020717 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 namespace tmbutils { template vector dnorm(vector x, T1 mean, T2 sd, int give_log=0) { vector logres; x=(x-mean)/sd; logres=-log(Type(sqrt(2*M_PI))*sd)-Type(.5)*x*x; if(give_log)return logres; else return exp(logres); } } // End namespace // Convenience utilites #include "spmat.hpp" #include "kronecker.hpp" #include "matexp.hpp" #include "order.hpp" #include "splines.hpp" #include "interpol.hpp" #include "density.hpp" #include "romberg.hpp" #include "autodiff.hpp" TMB/inst/include/tmbutils/autodiff.hpp0000644000176200001440000001217314536067013017462 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file \brief Easy access to AD library. */ /** \brief Automatic differentiation (gradient, hessian, jacobian) - Gives the TMB user easy access to the CppAD library */ namespace autodiff { /* Gradient */ template struct gradient_t { Functor f; gradient_t(Functor f_) : f(f_) {} AD userfun(vector > x){ return f(x); } vector operator()(vector x0){ CppAD::vector > x( x0 ); CppAD::vector > y( 1 ); CppAD::Independent(x); y[0] = userfun(x); CppAD::ADFun F(x, y); CppAD::vector x_eval(x0); return F.Jacobian(x_eval); } }; /** \brief Calculate gradient of vector function with scalar values \param F Functor with scalar values \param x Vector evaluation point \return Gradient vector \note The evaluation method of the functor must be templated Example: \code #include struct func { template T operator()(vector x){ // Evaluate function return exp( -x.sum() ); } }; template Type objective_function::operator() () { PARAMETER_VECTOR(theta); func f; // Calculate gradient vector g = autodiff::gradient(f, theta); REPORT(g); // Exit return 0; } \endcode */ template vector gradient(Functor F, vector x){ #ifdef CPPAD_FRAMEWORK gradient_t f(F); return f(x); #endif #ifdef TMBAD_FRAMEWORK TMBad::ADFun<> G(TMBad::StdWrap >(F), x); G = G.JacFun(); return G(x); #endif } /* Hessian */ template struct hessian_t { Functor f; gradient_t > gr; hessian_t(Functor f_) : f(f_), gr(f_) {} vector > userfun(vector > x){ return gr(x); } matrix operator()(vector x0){ CppAD::vector > x( x0 ); CppAD::vector > y( x0 ); CppAD::Independent(x); y = userfun(x); CppAD::ADFun F(x, y); CppAD::vector x_eval(x0); vector ans = F.Jacobian(x_eval); return asMatrix(ans, x.size(), x.size()); } }; /** \brief Calculate hessian of vector function with scalar values \param f Functor with scalar values \param x Vector evaluation point \return Hessian matrix \note The evaluation method of the functor must be templated Example: \code #include struct func { template T operator()(vector x){ // Evaluate function return exp( -x.sum() ); } }; template Type objective_function::operator() () { PARAMETER_VECTOR(theta); func f; // Calculate hessian matrix h = autodiff::hessian(f, theta); REPORT(h); // Exit return 0; } \endcode */ template matrix hessian(Functor f, vector x){ #ifdef CPPAD_FRAMEWORK hessian_t H(f); return H(x); #endif #ifdef TMBAD_FRAMEWORK TMBad::ADFun<> F(TMBad::StdWrap >(f), x); F = F.JacFun().JacFun(); vector Fx = F(x); return asMatrix(Fx, x.size(), x.size()); #endif } /* Jacobian */ template struct jacobian_t { Functor f; jacobian_t(Functor f_) : f(f_) {} vector > userfun(vector > x){ return f(x); } matrix operator()(vector x0){ CppAD::vector > x( x0 ); CppAD::Independent(x); CppAD::vector > y = userfun(x); CppAD::ADFun F(x, y); CppAD::vector x_eval(x0); vector ans = F.Jacobian(x_eval); // By row ! return asMatrix(ans, x.size(), y.size()).transpose(); } }; /** \brief Calculate jacobian of vector function with vector values \param f Functor with vector values \param x Vector evaluation point \return Jacobian matrix \note The evaluation method of the functor must be templated Example: \code #include struct func { template vector operator()(vector x){ // Evaluate function vector y(2); y(0) = x.sum(); y(1) = x.prod(); return y; } }; template Type objective_function::operator() () { PARAMETER_VECTOR(theta); func f; // Calculate jacobian matrix j = autodiff::jacobian(f, theta); REPORT(j); // Exit return 0; } \endcode */ template matrix jacobian(Functor f, vector x){ #ifdef CPPAD_FRAMEWORK jacobian_t J(f); return J(x); #endif #ifdef TMBAD_FRAMEWORK TMBad::ADFun<> J(TMBad::StdWrap >(f), x); int m = J.Range(); J = J.JacFun(); vector Jx = J(x); return asMatrix(Jx, x.size(), m).transpose(); #endif } } TMB/inst/include/tmbutils/order.hpp0000644000176200001440000000273214536067013016774 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file Taped sorting. */ namespace tmbutils { /** \brief Taped sorting of a vector. Example: \code order perm(x); vector xsort=perm(x); \endcode */ template class order{ public: vector iperm; matrix P; int n; order(vector x){ Type Zero=0; Type One=1; n=x.size(); iperm.resize(n); iperm.setZero(); P.resize(n,n); P.setZero(); /* Permutation vector - n^2 comparisons */ for(int i=0;i operator()(vector x){ vector y(x.size()); y.setZero(); /* y=P%*%x - n^2 flops */ for(int i=0;i operator()(array x){ array y(x); y.setZero(); /* y=P%*%x - n^2 flops */ for(int i=0;i struct SparseATx { // Eigens index type typedef typename Eigen::SparseMatrix::StorageIndex StorageIndex; // Sparse matrix (A) dimension and number of non zeros StorageIndex nrow, ncol, nnz; // Sparsity pattern (A) std::vector i; // Length nnz std::vector p; // Length ncol+1 SparseATx(const Eigen::SparseMatrix &x) : nrow(x.rows()), ncol(x.cols()), nnz(x.nonZeros()), i(x.innerIndexPtr(), x.innerIndexPtr() + nnz), p(x.outerIndexPtr(), x.outerIndexPtr() + ncol + 1) {} StorageIndex rows() const { return nrow; } StorageIndex cols() const { return ncol; } /* Operation: y = A^T * x */ template void f(const T *A, const T *x, T *y) { for (StorageIndex j = 0; j < ncol; j++) { y[j] = 0; for (StorageIndex k = p[j]; k < p[j+1]; k++) { y[j] += A[k] * x[i[k]]; // good access } } } /* Adjoint operation */ template void df(const T *A, const T *x, const T *y, T *dA, T *dx, const T *dy) { for (StorageIndex j = 0; j < ncol; j++) { for (StorageIndex k = p[j]; k < p[j+1]; k++) { dA[k] += x[i[k]] * dy[j]; // good access dx[i[k]] += A[k] * dy[j]; // bad access } } } }; template struct SpAxOp : TMBad::global::DynamicOperator< -1, -1> { typedef typename Eigen::SparseMatrix::StorageIndex StorageIndex; std::shared_ptr > P; SpAxOp() {} SpAxOp(const Eigen::SparseMatrix &x) : P(std::make_shared >( x )) { } static const bool have_input_size_output_size = true; TMBad::Index input_size() const { return 2; // Two pointers } TMBad::Index output_size() const { return (*P).cols(); } // FIXME: // static const bool forward_replay_copy = true; template void forward(TMBad::ForwardArgs &args) { const T* A = args.x_ptr(0); const T* x = args.x_ptr(1); T* y = args.y_ptr(0); (*P).template f(A, x, y); } template void reverse(TMBad::ReverseArgs &args) { const T* A = args.x_ptr(0); const T* x = args.x_ptr(1); const T* y = args.y_ptr(0); T* dA = args.dx_ptr(0); T* dx = args.dx_ptr(1); const T* dy = args.dy_ptr(0); (*P).template df(A, x, y, dA, dx, dy); } // ---- Dependencies ---- (copied from ad_blas) // FIXME: Make general implementation for pointer based case void dependencies(TMBad::Args<> &args, TMBad::Dependencies &dep) const { dep.add_segment(args.input(0), (*P).nnz ); dep.add_segment(args.input(1), (*P).rows() ); } static const bool have_dependencies = true; /** \brief This operator **has** implicit dependencies */ static const bool implicit_dependencies = true; /** \brief It is **not* safe to remap the inputs of this operator */ static const bool allow_remap = false; // Not yet implemented void forward(TMBad::ForwardArgs &args) { ASSERT(false); } void reverse(TMBad::ReverseArgs &args) { ASSERT(false); } const char* op_name() { return "SpAxOp"; } }; // FIXME: Remember to transpose A on construction /** \brief Shared configuration parameters for `expm_series` and `expm_generator` */ template struct config { /** \brief Normalize result? (expm_generator only) */ bool normalize; /** \brief Trace retaping? */ bool trace; /** \brief Warn if Nmax exceeded? */ bool warn; /** \brief Use no more than this number of terms in series. */ int Nmax; config() : normalize(false), trace(true), warn(true), Nmax(100) {} }; /** \brief Matrix exponential multiplied by vector This shared atomic operator can be used in cases where `x^T*exp(A)` needs to be calculated many times for same sparsity pattern. The number of terms (N) in series can be variable and retaping is triggered if (and only if) N changes compared to previous evaluation. \note Multiplication with vector is from the left: `x^T * exp(A)` */ template struct expm_series { typedef vectorize::vector vec; /** Number of terms */ T N; /** Vector of sparse matrix non zeros */ vec A_values; /** Operator that multiplies sparse matrix with vector */ TMBad::global::Complete > multiply; /** ADFun object that holds the entire matexp tape */ TMBad::ADFun_packed<> F; /** Configuration */ config cfg; /** Helper to update generator */ void update(Eigen::SparseMatrix &A) { // FIXME: Assert same pattern A_values = vec(A.valuePtr(), A.nonZeros()); } expm_series() {} expm_series(Eigen::SparseMatrix &A, T N, config cfg=config()) : N(N), A_values(A.valuePtr(), A.nonZeros()), multiply(A), cfg(cfg) { } /** \brief Evaluate `x^T*exp(A)` */ vec operator()(vec x) { N = min(N, T(cfg.Nmax)); std::vector args = {A_values, x, vec(N, 1)}; if (! F.initialized() ) { struct Test { config cfg; TMBad::Scalar Nold; bool operator() (const std::vector &x) { using TMBad::operator<<; TMBad::Scalar N = x[2][0]; if ( (int) N == cfg.Nmax) { if (cfg.warn) Rf_warning("expm: N terms reduced to Nmax (%i)", (int) cfg.Nmax); } bool change = (Nold != N); if (cfg.trace && change) { Rcout << "Retaping:" << " Nold=" << Nold << " Nnew=" << N << "\n"; Nold = N; } return change; } }; Test N_changed = {cfg, N.Value()}; F = TMBad::ADFun_retaping(*this, args, N_changed); } return F(args); } private: friend class TMBad::PackWrap; // Packed: (A, x) -> exp(A) * x TMBad::ad_segment operator() (const std::vector &args) { // Unpack input vec A = args[0]; vec x = args[1]; vec N_= args[2]; int N = (int) N_[0].Value(); // Evaluate series vec term(x), y(x); for (int n=1; n struct expm_series { typedef vectorize::vector vec; int N; Eigen::SparseMatrix A; config cfg; void update(Eigen::SparseMatrix &A) { this->A = A; } expm_series() {} expm_series(const Eigen::SparseMatrix &A, double N, config cfg=config()) : N(N), A(A), cfg(cfg) { if ((int) N > cfg.Nmax) { if (cfg.warn) Rf_warning("expm: N terms reduced to Nmax (%i)", (int) cfg.Nmax); this->N = cfg.Nmax; } } vec operator()(vec x) { // Evaluate series vec term(x), y(x); for (int n=1; n struct expm_generator { typedef vectorize::vector vec; expm_series ExpA; T rho; /** \brief Uniformization Grassmann (1977) eq. 10. => error < 1e-4 `rho=abs(max(diag(Q)))` */ T getN(T rho) { return ceil(rho + 4*sqrt(rho) + 5); } // FIXME: Calculate rho=abs(max(diag(Q))) expm_generator(Eigen::SparseMatrix &Q, config cfg=config()) { using TMBad::min; Eigen::SparseMatrix A(Q); vector d = Q.diagonal(); if (d.size() > 0) { T M = d[0]; for (int i=1; i(A, getN(rho), cfg); } /** \brief Evaluate `x^T*exp(Q)` */ vec operator()(vec x) { vec y = ExpA(x); y = exp(-rho) * y; if (ExpA.cfg.normalize) { y = y / sum(y); } return y; } }; } // End namespace #endif TMB/inst/include/dnorm.hpp0000644000176200001440000000140214536067013015126 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file \brief Univariate normal density \ingroup R_style_distribution */ /** \brief Probability density function of the normal distribution \ingroup R_style_distribution \param x vector of observations \param mean mean of the normal distribution \param sd standard deviation of the normal distribution. must be strictly positive. \param give_log true if one wants the log-probability, false otherwise. */ template Type dnorm(Type x, Type mean, Type sd, int give_log=0) { Type resid = (x - mean) / sd; Type logans = Type(-log(sqrt(2*M_PI))) - log(sd) - Type(.5) * resid * resid; if(give_log) return logans; else return exp(logans); } VECTORIZE4_ttti(dnorm) TMB/inst/include/checkpoint_macro.hpp0000644000176200001440000002743114536067013017331 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /* Given function f0. Define recursively higher order reverse mode derivatives: f0: R^(n) -> R^(m) ( x -> f0 (x) ) f1: R^(n+m) -> R^(n) ( (x,w1) -> f0'(x)*w1 ) f2: R^(n+m+n) -> R^(n+m) ( (x,w1,w2) -> f1'(x)*w2 ) f3: R^(n+m+n+n+m) -> R^(n+m+n) ( (x,w1,w2,w3) -> f2'(x)*w3 ) 1. We define a 'generalized symbol' to represent all of these. _Reverse_mode_AD_ is trivially obtained for this symbol by calling itself on a higher level. Each occurance on the tape will occupy O(n+m) memory units independent on the number of flops performed by f0. 2. _Double_versions_ of the generalized symbol are obtained using nested AD types to tape f0, then recursively tape forward and reverse mode sweeps. Finally, given (1) and (2) the macro TMB_ATOMIC_VECTOR_FUNCTION will generate the atomic symbol. */ /* general helper functions */ #ifdef CPPAD_FRAMEWORK namespace atomic{ /** \name User defined atomic functions \note The following procedure is automatically performed with the macro REGISTER_ATOMIC. \verbatim Given function f0. Define recursively higher order reverse mode derivatives: f0: R^(n) -> R^(m) ( x -> f0 (x) ) f1: R^(n+m) -> R^(n) ( (x,w1) -> f0'(x)*w1 ) f2: R^(n+m+n) -> R^(n+m) ( (x,w1,w2) -> f1'(x)*w2 ) f3: R^(n+m+n+n+m) -> R^(n+m+n) ( (x,w1,w2,w3) -> f2'(x)*w3 ) 1. We define a 'generalized symbol' to represent all of these. _Reverse_mode_AD_ is trivially obtained for this symbol by calling itself on a higher level. Each occurance on the tape will occupy O(n+m) memory units independent of the number of flops performed by f0. 2. _Double_versions_ of the generalized symbol are obtained using nested AD types to tape f0, then recursively tape forward and reverse mode sweeps. Finally, given (1) and (2) the macro TMB_ATOMIC_VECTOR_FUNCTION will generate the atomic symbol. \endverbatim @{ */ /** \brief Construct a tape of a given template _functor_ (Will be used to tape 'f0' for different nested AD types) */ template CppAD::ADFun* generate_tape(Func f, vector x_){ Rcout << "Generating tape\n"; int n=x_.size(); vector > x(n); for(int i=0;i(x_[i]); CppAD::Independent(x); vector > y=f(x); vector > y2(y.size()); for(int i=0;i* padf=new CppAD::ADFun(x,y2); return padf; } /** \brief Lift tape of fn up one level by taping forward and reverse sweeps. Note: x_ needs only have length equal to the input domain dimension of f0. Zeros are filled in for all range directions. */ template CppAD::ADFun* forrev(CppAD::ADFun >* padf, vector x_){ size_t n=padf->Domain(); size_t m=padf->Range(); vector > x(n+m); vector > y(n); for(int i=0;i(x_[i]); for(int i=x_.size();i(0); vector > tmp1(n); vector > tmp2(m); CppAD::Independent(x); for(size_t i=0;iForward(0,tmp1); y = padf->Reverse(1,tmp2); CppAD::ADFun* padf2=new CppAD::ADFun(x,y); delete padf; return padf2; } /** \brief Recursively apply forrev until the lowest Base level (double) */ template CppAD::ADFun* multi_forrev(CppAD::ADFun* padf, vector x_){ return multi_forrev(forrev(padf, x_), x_); } template <> CppAD::ADFun* multi_forrev(CppAD::ADFun* padf, vector x_) CSKIP({ return padf; }) /** \brief Tape symbol up to any order */ template CppAD::ADFun* tape_symbol(Func f, vector x){ typedef typename Func::ScalarType::value_type Base; CppAD::ADFun* f0=generate_tape(f,x); CppAD::ADFun* fn=multi_forrev(f0,x); return fn; } #ifdef _OPENMP #define NTHREADS config.nthreads #define THREAD omp_get_thread_num() #else #define NTHREADS 1 #define THREAD 0 #endif /** \brief General class to construct 'double versions' of the generalized symbol. */ template class UserFunctor> struct forrev_derivatives{ bool initialized; int n,m; forrev_derivatives(){ initialized=false; } /* ADFun pointers used by the double versions indexed as vpf[thread][level] */ CppAD::vector* > > vpf; void cpyADfunPointer(CppAD::ADFun* padf, int i){ padf->optimize(); vpf[0][i] = padf; /* Copy object for other threads */ for(int thread=1;thread(); vpf[thread][i]->operator=(*padf); } } void do_init(vector x){ UserFunctor f; n=x.size(); m=f(x).size(); UserFunctor > f0; UserFunctor > > f1; UserFunctor > > > f2; UserFunctor > > > > f3; vpf.resize(NTHREADS); for(int thread=0;thread x){ if(!initialized){ do_init(x); initialized=true; } } int get_output_dim(int input_dim){ int output_dim=-1; // Fibonacci type recursion for each 'column' if (input_dim == n) output_dim = m; else if (input_dim == n+m) output_dim = n; else if (input_dim == n+m+n) output_dim = n+m; else if (input_dim == n+m+n+n+m) output_dim = n+m+n; else Rf_error("get_output_dim failed"); return output_dim; } // Calculate level from input dimension int get_level(int input_dim){ int level=-1; if (input_dim == n) level = 0; else if (input_dim == n+m) level = 1; else if (input_dim == n+m+n) level = 2; else if (input_dim == n+m+n+n+m) level = 3; else Rf_error("get_level failed"); return level; } // Evaluate CppAD::vector operator()(CppAD::vector tx){ int level = get_level(tx.size()); return vpf[THREAD][level]->Forward(0,tx); } }; /* end class forrev_derivatives */ #undef NTHREADS #undef THREAD /** \brief Wrap user function into a functor, generate double versions, and construct atomic function in a namespace */ #define REGISTER_ATOMIC(USERFUNCTION) \ namespace USERFUNCTION##NAMESPACE{ \ template \ struct UserFunctor{ \ typedef Type ScalarType; \ vector operator()(vector x){ \ return USERFUNCTION(x); \ } \ }; \ atomic::forrev_derivatives double_version; \ TMB_ATOMIC_VECTOR_FUNCTION( \ generalized_symbol \ , \ double_version.get_output_dim(tx.size()) \ , \ ty = double_version(tx); \ , \ CppAD::vector concat(tx.size() + py.size()); \ for(size_t i=0; i < tx.size(); i++) concat[i] = tx[i]; \ for(size_t i=0; i < py.size(); i++) concat[tx.size()+i] = py[i]; \ px = generalized_symbol(concat); \ ) \ template \ vector generalized_symbol(vector x){ \ CppAD::vector xx(x.size()); \ for(int i=0;i yy=generalized_symbol(xx); \ vector y(yy.size()); \ for(int i=0;i USERFUNCTION(vector x){ \ USERFUNCTION##NAMESPACE::double_version.init(x); \ return USERFUNCTION##NAMESPACE::generalized_symbol(x); \ } \ vector > USERFUNCTION(vector > x){ \ return USERFUNCTION##NAMESPACE::generalized_symbol(x); \ } \ vector > > USERFUNCTION(vector > > x){ \ return USERFUNCTION##NAMESPACE::generalized_symbol(x); \ } \ vector > > > USERFUNCTION(vector > > > x){ \ return USERFUNCTION##NAMESPACE::generalized_symbol(x); \ } /** @} */ } /* end namespace atomic */ #endif // CPPAD_FRAMEWORK #ifdef TMBAD_FRAMEWORK namespace atomic { /** \brief User interface to checkpointing using TMBad \details This is the recommended way of constucting atomic functions without knowing the reverse mode derivatives. Usage: Within `objective_function` (or any other function) one can do ``` AtomicLocal F(Functor()); ``` - Each call to `F(x)` only generates one new operatation on the ad stack. - Thread safe because local. - `F` is owned by the operation stack and is automatically freed when no longer needed. */ template struct AtomicLocal { typedef TMBad::StdWrap > StdWrapFunctor; Functor F; TMBad::ADFun<> Tape; AtomicLocal(const Functor &F) : F(F) {} template vector operator()(const vector &x) { if ( (size_t) x.size() != Tape.Domain() ) { Tape = TMBad::ADFun<>( StdWrapFunctor(F), x).atomic(); } std::vector x_(x.data(), x.data() + x.size()); std::vector y_ = Tape(x_); vector y(y_); return y; } vector operator()(const vector &x) { return F(x); } }; /** \brief For backwards compatibility with CppAD \details Allocate an atomic function for each thread. Main purpuse is to support the `REGISTER_ATOMIC` macro. \tparam Functor assumed to have a default CTOR \warning Static atomic functions are never freed. */ template struct AtomicGlobal { #ifdef _OPENMP #define NTHREADS config.nthreads #define THREAD omp_get_thread_num() #else #define NTHREADS 1 #define THREAD 0 #endif std::vector< AtomicLocal >* p_; AtomicGlobal() { static std::vector< AtomicLocal >* p = new std::vector< AtomicLocal > (NTHREADS, Functor() ); p_ = p; } template vector operator()(const vector &x) { return ((*p_)[THREAD])(x); } #undef NTHREADS #undef THREAD }; #define REGISTER_ATOMIC(USERFUNCTION) \ namespace USERFUNCTION##NAMESPACE { \ template \ struct UserFunctor { \ typedef Type ScalarType; \ vector operator()(const vector &x) { \ return USERFUNCTION(x); \ } \ }; \ } \ vector USERFUNCTION(const vector &x) { \ typedef USERFUNCTION##NAMESPACE::UserFunctor Functor; \ return atomic::AtomicGlobal()(x); \ } \ vector USERFUNCTION(const vector &x) { \ typedef USERFUNCTION##NAMESPACE::UserFunctor Functor; \ return atomic::AtomicGlobal()(x); \ } } // End namespace atomic #endif // TMBAD_FRAMEWORK TMB/inst/include/toggle_thread_safe_R.hpp0000644000176200001440000000716314536067013020110 0ustar liggesusers/** \file \brief Override subset of R-API with thread safe versions. This file is included by `TMB.hpp` if compiled with `_OPENMP`. It overrides a selected subset of the R-API with thread safe versions (FIXME: Still some missing?). If, for some reason, you want to undo the re-defines: ``` #ifdef TMB_HAVE_THREAD_SAFE_R #include #endif ``` However, note that this is **not** recommended (the R macros are often used from the user template through at least `DATA_STRUCT()` and `DATA_UPDATE()`). \note To minimize overhead one should use as few R-API calls as possible, i.e. avoid doing REAL(x)[i] in a loop. */ #ifdef _OPENMP #ifndef TMB_HAVE_THREAD_SAFE_R inline SEXP Ts_getAttrib(SEXP x, SEXP y) { SEXP ans; #pragma omp critical { ans = Rf_getAttrib(x, y); } return ans; } inline SEXP Ts_STRING_ELT(SEXP x, size_t i) { SEXP ans; #pragma omp critical { ans = STRING_ELT(x, i); } return ans; } inline const char* Ts_CHAR(SEXP x) { const char* ans; #pragma omp critical { ans = R_CHAR(x); } return ans; } inline SEXP Ts_VECTOR_ELT(SEXP x, size_t i) { SEXP ans; #pragma omp critical { ans = VECTOR_ELT(x, i); } return ans; } inline R_len_t Ts_length(SEXP x) { R_len_t ans; #pragma omp critical { ans = Rf_length(x); } return ans; } inline int* Ts_INTEGER(SEXP x) { int* ans; #pragma omp critical { ans = INTEGER(x); } return ans; } inline double* Ts_REAL(SEXP x) { double* ans; #pragma omp critical { ans = REAL(x); } return ans; } extern "C" inline void Ts_GetRNGstate() { #pragma omp critical { GetRNGstate(); } // Wait for all threads to get to this point #pragma omp barrier } inline Rboolean Ts_isNumeric(SEXP x) { Rboolean ans; #pragma omp critical { ans = Rf_isNumeric(x); } return ans; } inline int Ts_LENGTH(SEXP x) { int ans; #pragma omp critical { ans = LENGTH(x); } return ans; } inline R_xlen_t Ts_XLENGTH(SEXP x) { R_xlen_t ans; #pragma omp critical { ans = XLENGTH(x); } return ans; } inline SEXP Ts_install(const char *x) { SEXP ans; #pragma omp critical { ans = Rf_install(x); } return ans; } inline SEXP Ts_findVar(SEXP x, SEXP y) { SEXP ans; #pragma omp critical { ans = Rf_findVar(x, y); } return ans; } inline SEXP Ts_ENCLOS(SEXP x) { SEXP ans; #pragma omp critical { ans = ENCLOS(x); } return ans; } inline void Ts_warning(const char *x, ...) { if (omp_get_thread_num() == 0) { Rf_warning("%s",x); } } /* --- Re-define ---------------------------------------------------------- */ #define TMB_HAVE_THREAD_SAFE_R #define Rf_getAttrib Ts_getAttrib #define STRING_ELT Ts_STRING_ELT #undef CHAR #define CHAR(x) Ts_CHAR(x) #define VECTOR_ELT Ts_VECTOR_ELT #define Rf_length Ts_length #define INTEGER Ts_INTEGER #define REAL Ts_REAL #define GetRNGstate Ts_GetRNGstate #define Rf_isNumeric Ts_isNumeric #define LENGTH Ts_LENGTH #define XLENGTH Ts_XLENGTH #define Rf_install Ts_install #define Rf_findVar Ts_findVar #define ENCLOS Ts_ENCLOS #define Rf_warning Ts_warning #else /* --- Un-define ---------------------------------------------------------- */ #undef TMB_HAVE_THREAD_SAFE_R #undef Rf_getAttrib #undef STRING_ELT #undef CHAR #define CHAR(x) R_CHAR(x) #undef VECTOR_ELT #undef Rf_length #undef INTEGER #undef REAL #undef GetRNGstate #undef Rf_isNumeric #undef LENGTH #undef XLENGTH #undef Rf_install #undef Rf_findVar #undef ENCLOS #undef Rf_warning #endif // TMB_HAVE_THREAD_SAFE_R #endif // _OPENMP TMB/inst/include/atomic_convolve.hpp0000644000176200001440000000623314536067013017205 0ustar liggesusers// Copyright (C) 2013-2016 Kasper Kristensen // License: GPL-2 namespace atomic { /* Workhorse version (used while sweeping - pre-allocated output) */ Eigen::MatrixXd convol2d_work(const Eigen::MatrixXd& x, const Eigen::MatrixXd& K) CSKIP({ int kr = K.rows(); int kc = K.cols(); Eigen::MatrixXd y(x.rows() - kr + 1, x.cols() - kc + 1); for (int i = 0; i < y.rows(); i++) for (int j = 0; j < y.cols(); j++) y(i, j) = (x.block(i, j, kr, kc).array() * K.array()).sum(); return y; }) /* Forward declare version used while taping (for AD types) */ template matrix convol2d(const Eigen::MatrixBase& x, const Eigen::MatrixBase& K); TMB_ATOMIC_VECTOR_FUNCTION( // ATOMIC_NAME convol2d, // OUTPUT_DIM (CppAD::Integer(tx[0]) - CppAD::Integer(tx[2]) + 1) * (CppAD::Integer(tx[1]) - CppAD::Integer(tx[3]) + 1), // ATOMIC_DOUBLE typedef TypeDefs::MapMatrix MapMatrix_t; typedef TypeDefs::ConstMapMatrix ConstMapMatrix_t; int nx1 = CppAD::Integer(tx[0]); int nx2 = CppAD::Integer(tx[1]); int nk1 = CppAD::Integer(tx[2]); int nk2 = CppAD::Integer(tx[3]); int ny1 = nx1 - nk1 + 1; int ny2 = nx2 - nk2 + 1; ConstMapMatrix_t X(&tx[4 ], nx1, nx2); ConstMapMatrix_t K(&tx[4 + nx1 * nx2], nk1, nk2); MapMatrix_t Y(&ty[0 ], ny1, ny2); Y = convol2d_work(X, K); , // ATOMIC_REVERSE typedef typename TypeDefs::MapMatrix MapMatrix_t; typedef typename TypeDefs::ConstMapMatrix ConstMapMatrix_t; int nx1 = CppAD::Integer(tx[0]); int nx2 = CppAD::Integer(tx[1]); int nk1 = CppAD::Integer(tx[2]); int nk2 = CppAD::Integer(tx[3]); int ny1 = nx1 - nk1 + 1; int ny2 = nx2 - nk2 + 1; ConstMapMatrix_t X(&tx[4 ], nx1, nx2); ConstMapMatrix_t K(&tx[4 + nx1 * nx2], nk1, nk2); ConstMapMatrix_t Y(&ty[0 ], ny1, ny2); ConstMapMatrix_t W(&py[0 ], ny1, ny2); matrix Kflip = K.reverse(); matrix Wexpand(W.rows() + 2 * (K.rows() - 1), W.cols() + 2 * (K.cols() - 1)); Wexpand.setZero(); Wexpand.block(K.rows() - 1, K.cols() - 1, W.rows(), W.cols()) = W; MapMatrix_t P0(&px[0 ], 1, 4); MapMatrix_t PX(&px[4 ], nx1, nx2); MapMatrix_t PK(&px[4 + nx1 * nx2], nk1, nk2); P0.setZero(); PX = convol2d(Wexpand, Kflip); PK = convol2d( X, W); ) /* Implementation of the forward declared version */ template matrix convol2d( const Eigen::MatrixBase& x, const Eigen::MatrixBase& K) { typedef typename DerivedA::Scalar Type; CppAD::vector arg(4 + x.size() + K.size()); arg[0] = x.rows(); arg[1] = x.cols(); arg[2] = K.rows(); arg[3] = K.cols(); for (int i = 0; i < x.size(); i++) { arg[4 + i] = x(i); } for (int i = 0; i < K.size(); i++) { arg[4 + i + x.size()] = K(i); } CppAD::vector res = convol2d(arg); matrix y = vec2mat(res, x.rows() - K.rows() + 1, x.cols() - K.cols() + 1); return y; } } TMB/inst/include/distributions_R.hpp0000644000176200001440000005563214536067013017210 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file \brief Probability distribution functions. */ /** \brief Distribution function of the normal distribution (following R argument convention). \ingroup R_style_distribution */ template Type pnorm(Type q, Type mean = 0., Type sd = 1.){ CppAD::vector tx(1); tx[0] = (q - mean) / sd; return atomic::pnorm1(tx)[0]; } VECTORIZE3_ttt(pnorm) VECTORIZE1_t(pnorm) /** \brief Quantile function of the normal distribution (following R argument convention). \ingroup R_style_distribution */ template Type qnorm(Type p, Type mean = 0., Type sd = 1.){ CppAD::vector tx(1); tx[0] = p; return sd*atomic::qnorm1(tx)[0] + mean; } VECTORIZE3_ttt(qnorm) VECTORIZE1_t(qnorm) /** \brief Distribution function of the gamma distribution (following R argument convention). \ingroup R_style_distribution */ template Type pgamma(Type q, Type shape, Type scale = 1.){ CppAD::vector tx(4); tx[0] = q/scale; tx[1] = shape; tx[2] = Type(0); // 0'order deriv tx[3] = -lgamma(shape); // normalize return atomic::D_incpl_gamma_shape(tx)[0]; } VECTORIZE3_ttt(pgamma) /** \brief Quantile function of the gamma distribution (following R argument convention). \ingroup R_style_distribution */ template Type qgamma(Type q, Type shape, Type scale = 1.){ CppAD::vector tx(3); tx[0] = q; tx[1] = shape; tx[2] = -lgamma(shape); // normalize return atomic::inv_incpl_gamma(tx)[0] * scale; } VECTORIZE3_ttt(qgamma) /** \brief Distribution function of the poisson distribution (following R argument convention). \ingroup R_style_distribution */ template Type ppois(Type q, Type lambda){ CppAD::vector tx(2); tx[0] = q; tx[1] = lambda; return atomic::ppois(tx)[0]; } VECTORIZE2_tt(ppois) /** @name Exponential distribution. Functions relative to the exponential distribution. */ /**@{*/ /** \brief Cumulative distribution function of the exponential distribution. \ingroup R_style_distribution \param rate Rate parameter. Must be strictly positive. */ template Type pexp(Type x, Type rate) { return CppAD::CondExpGe(x,Type(0),1-exp(-rate*x),Type(0)); } // Vectorize pexp VECTORIZE2_tt(pexp) /** \brief Probability density function of the exponential distribution. \ingroup R_style_distribution \param rate Rate parameter. Must be strictly positive. \param give_log true if one wants the log-probability, false otherwise. */ template Type dexp(Type x, Type rate, int give_log=0) { if(!give_log) return CppAD::CondExpGe(x,Type(0),rate*exp(-rate*x),Type(0)); else return CppAD::CondExpGe(x,Type(0),log(rate)-rate*x,Type(-INFINITY)); } // Vectorize dexp VECTORIZE3_tti(dexp) /** \brief Inverse cumulative distribution function of the exponential distribution. \ingroup R_style_distribution \param rate Rate parameter. Must be strictly positive. */ template Type qexp(Type p, Type rate) { return -log(1-p)/rate; } // Vectorize qexp. VECTORIZE2_tt(qexp) /**@}*/ /** @name Weibull distribution. Functions relative to the Weibull distribution. */ /**@{*/ /** \brief Cumulative distribution function of the Weibull distribution. \ingroup R_style_distribution \param shape Shape parameter. Must be strictly positive. \param scale Scale parameter. Must be strictly positive. */ template Type pweibull(Type x, Type shape, Type scale) { return CppAD::CondExpGe(x,Type(0),1-exp(-pow(x/scale,shape)),Type(0)); } // Vectorize pweibull VECTORIZE3_ttt(pweibull) /** \brief Probability density function of the Weibull distribution. \ingroup R_style_distribution \param shape Shape parameter. Must be strictly positive. \param scale Scale parameter. Must be strictly positive. \param give_log true if one wants the log-probability, false otherwise. */ template Type dweibull(Type x, Type shape, Type scale, int give_log=0) { if(!give_log) return CppAD::CondExpGe(x,Type(0),shape/scale * pow(x/scale,shape-1) * exp(-pow(x/scale,shape)),Type(0)); else return CppAD::CondExpGe(x,Type(0),log(shape) - log(scale) + (shape-1)*(log(x)-log(scale)) - pow(x/scale,shape),Type(-INFINITY)); } // Vectorize dweibull VECTORIZE4_ttti(dweibull) /** \brief Inverse cumulative distribution function of the Weibull distribution. \ingroup R_style_distribution \param p Probability ; must be between 0 and 1. \param shape Shape parameter. Must be strictly positive. \param scale Scale parameter. Must be strictly positive. */ template Type qweibull(Type p, Type shape, Type scale) { Type res = scale * pow( (-log(1-p)) , 1/shape ); res = CppAD::CondExpLt(p,Type(0),Type(0),res); res = CppAD::CondExpGt(p,Type(1),Type(0),res); return res; } // Vectorize qweibull VECTORIZE3_ttt(qweibull) /**@}*/ /** \brief Probability mass function of the binomial distribution. \ingroup R_style_distribution \param k Number of successes. \param size Number of trials. \param prob Probability of success. \param give_log true if one wants the log-probability, false otherwise. */ template Type dbinom(Type k, Type size, Type prob, int give_log=0) { Type logres = lgamma(size + 1) - lgamma(k + 1) - lgamma(size - k + 1); // Add 'k * log(prob)' only if k > 0 logres += CppAD::CondExpGt(k, Type(0), k * log(prob), Type(0) ); // Add '(size - k) * log(1 - prob)' only if size > k logres += CppAD::CondExpGt(size, k, (size - k) * log(1 - prob), Type(0) ); if (!give_log) return exp(logres); else return logres; } // Vectorize dbinom VECTORIZE4_ttti(dbinom) /** \brief Density of binomial distribution parameterized via logit(prob) This version should be preferred when working on the logit scale as it is numerically stable for probabilities close to 0 or 1. \ingroup R_style_distribution */ template Type dbinom_robust(Type k, Type size, Type logit_p, int give_log=0) { CppAD::vector tx(4); tx[0] = k; tx[1] = size; tx[2] = logit_p; tx[3] = 0; Type ans = atomic::log_dbinom_robust(tx)[0]; /* without norm. constant */ if (size > 1) { ans += lgamma(size+1.) - lgamma(k+1.) - lgamma(size-k+1.); } return ( give_log ? ans : exp(ans) ); } VECTORIZE4_ttti(dbinom_robust) /** \brief Probability density function of the beta distribution. \ingroup R_style_distribution \param shape1 First shape parameter. Must be strictly positive. \param shape2 Second shape parameter. Must be strictly positive. \param give_log true if one wants the log-probability, false otherwise. */ template Type dbeta(Type x, Type shape1, Type shape2, int give_log) { Type res = exp(lgamma(shape1+shape2) - lgamma(shape1) - lgamma(shape2)) * pow(x,shape1-1) * pow(1-x,shape2-1); if(!give_log) return res; else return CppAD::CondExpEq(x,Type(0),log(res),lgamma(shape1+shape2) - lgamma(shape1) - lgamma(shape2) + (shape1-1)*log(x) + (shape2-1)*log(1-x)); } // Vectorize dbeta VECTORIZE4_ttti(dbeta) /** \brief Probability density function of the Fisher distribution. \ingroup R_style_distribution \param df1 Degrees of freedom 1. \param df2 Degrees of freedom 2. \param give_log true if one wants the log-probability, false otherwise. */ template Type df(Type x, Type df1, Type df2, int give_log) { Type logres = lgamma((df1+df2)/2.) - lgamma(df1/2.) - lgamma(df2/2.) + df1/2.*log(Type(df1)/df2) + (df1/2.-1)*log(x) - (df1+df2)/2.*log(1+Type(df1)/df2*x); if(!give_log) return exp(logres); else return logres; } //Vectorize df VECTORIZE4_ttti(df) /** \brief Probability density function of the logistic distribution. \ingroup R_style_distribution \param location Location parameter. \param scale Scale parameter. Must be strictly positive. \param give_log true if one wants the log-probability, false otherwise. */ template Type dlogis(Type x, Type location, Type scale, int give_log) { Type logres = -(x-location)/scale - log(scale) - 2*log(1+exp(-(x-location)/scale)); if(!give_log) return exp(logres); else return logres; } // Vectorize dlogis VECTORIZE4_ttti(dlogis) /** \brief Probability density function of the skew-normal distribution. \ingroup R_style_distribution \param alpha Slant parameter. \param give_log true if one wants the log-probability, false otherwise. */ template Type dsn(Type x, Type alpha, int give_log=0) { if(!give_log) return 2 * dnorm(x,Type(0),Type(1),0) * pnorm(alpha*x); else return log(2.0) + log(dnorm(x,Type(0),Type(1),0)) + log(pnorm(alpha*x)); } // Vectorize dsn VECTORIZE3_tti(dsn) /** \brief Probability density function of the Student t-distribution. \ingroup R_style_distribution \param df Degree of freedom. \param give_log true if one wants the log-probability, false otherwise. */ template Type dt(Type x, Type df, int give_log) { Type logres = lgamma((df+1)/2) - Type(1)/2*log(df*M_PI) -lgamma(df/2) - (df+1)/2*log(1+x*x/df); if(!give_log) return exp(logres); else return logres; } // Vectorize dt VECTORIZE3_tti(dt) /** \brief Probability mass function of the multinomial distribution. \ingroup R_style_distribution \param x Vector of length K of integers. \param p Vector of length K, specifying the probability for the K classes (note, unlike in R these must sum to 1). \param give_log true if one wants the log-probability, false otherwise. */ template Type dmultinom(vector x, vector p, int give_log=0) { vector xp1 = x+Type(1); Type logres = lgamma(x.sum() + Type(1)) - lgamma(xp1).sum() + (x*log(p)).sum(); if(give_log) return logres; else return exp(logres); } /** @name Sinh-asinh distribution. Functions relative to the sinh-asinh distribution. */ /**@{*/ /** \brief Probability density function of the sinh-asinh distribution. \ingroup R_style_distribution \param mu Location. \param sigma Scale. \param nu Skewness. \param tau Kurtosis. \param give_log true if one wants the log-probability, false otherwise. Notation adopted from R package "gamlss.dist". Probability density given in (2) in __Jones and Pewsey (2009) Biometrika (2009) 96 (4): 761-780__. It is not possible to call this function with nu a vector or tau a vector. */ template Type dSHASHo(Type x, Type mu, Type sigma, Type nu, Type tau, int give_log = 0) { // TODO : Replace log(x+sqrt(x^2+1)) by a better approximation for asinh(x). Type z = (x-mu)/sigma; Type c = cosh(tau*log(z+sqrt(z*z+1))-nu); Type r = sinh(tau*log(z+sqrt(z*z+1))-nu); Type logres = -log(sigma) + log(tau) -0.5*log(2*M_PI) -0.5*log(1+(z*z)) +log(c) -0.5*(r*r); if(!give_log) return exp(logres); else return logres; } // Vectorize dSHASHo VECTORIZE6_ttttti(dSHASHo) /** \brief Cumulative distribution function of the sinh-asinh distribution. \ingroup R_style_distribution \param mu Location. \param sigma Scale. \param nu Skewness. \param tau Kurtosis. \param give_log true if one wants the log-probability, false otherwise. Notation adopted from R package "gamlss.dist". It is not possible to call this function with nu a vector or tau a vector. */ template Type pSHASHo(Type q,Type mu,Type sigma,Type nu,Type tau,int give_log=0) { // TODO : Replace log(x+sqrt(x^2+1)) by a better approximation for asinh(x). Type z = (q-mu)/sigma; Type r = sinh(tau * log(z+sqrt(z*z+1)) - nu); Type p = pnorm(r); if (!give_log) return p; else return log(p); } // Vectorize pSHASHo VECTORIZE6_ttttti(pSHASHo) /** \brief Quantile function of the sinh-asinh distribution. \ingroup R_style_distribution \param mu Location. \param sigma Scale. \param nu Skewness. \param tau Kurtosis. \param log_p true if p is log-probability, false otherwise. Notation adopted from R package "gamlss.dist". It is not possible to call this function with nu a vector or tau a vector. */ template Type qSHASHo(Type p, Type mu, Type sigma, Type nu, Type tau, int log_p = 0) { // TODO : Replace log(x+sqrt(x^2+1)) by a better approximation for asinh(x). if(!log_p) return mu + sigma*sinh((1/tau)* log(qnorm(p)+sqrt(qnorm(p)*qnorm(p)+1)) + (nu/tau)); else return mu + sigma*sinh((1/tau)*log(qnorm(exp(p))+sqrt(qnorm(exp(p))*qnorm(exp(p))+1))+(nu/tau)); } // Vectorize qSHASHo VECTORIZE6_ttttti(qSHASHo) /** \brief Transforms a normal variable into a sinh-asinh variable. \param mu Location parameter of the result sinh-asinh distribution. \param sigma Scale parameter of the result sinh-asinh distribution. \param nu Skewness parameter of the result sinh-asinh distribution. \param tau Kurtosis parameter of the result sinh-asinh distribution. \param log_p true if p is log-probability, false otherwise. It is not possible to call this function with nu a vector or tau a vector. */ template Type norm2SHASHo(Type x, Type mu, Type sigma, Type nu, Type tau, int log_p = 0) { return qSHASHo(pnorm(x),mu,sigma,nu,tau,log_p); } // Vectorize norm2SHASHo VECTORIZE6_ttttti(norm2SHASHo) /**@}*/ /** \brief Distribution function of the beta distribution (following R argument convention). \note Non-centrality parameter (ncp) not implemented. \ingroup R_style_distribution */ template Type pbeta(Type q, Type shape1, Type shape2){ CppAD::vector tx(4); tx[0] = q; tx[1] = shape1; tx[2] = shape2; tx[3] = 0; // order Type ans = atomic::pbeta(tx)[0]; return ans; } VECTORIZE3_ttt(pbeta) /** \brief Quantile function of the beta distribution (following R argument convention). \note Non-centrality parameter (ncp) not implemented. \ingroup R_style_distribution */ template Type qbeta(Type p, Type shape1, Type shape2){ CppAD::vector tx(3); tx[0] = p; tx[1] = shape1; tx[2] = shape2; Type ans = atomic::qbeta(tx)[0]; return ans; } VECTORIZE3_ttt(qbeta) /** \brief besselK function (same as besselK from R). \note Derivatives wrt. both arguments are implemented \ingroup special_functions */ template Type besselK(Type x, Type nu){ Type ans; if(CppAD::Variable(nu)) { CppAD::vector tx(3); tx[0] = x; tx[1] = nu; tx[2] = 0; ans = atomic::bessel_k(tx)[0]; } else { CppAD::vector tx(2); tx[0] = x; tx[1] = nu; ans = atomic::bessel_k_10(tx)[0]; } return ans; } VECTORIZE2_tt(besselK) /** \brief besselI function (same as besselI from R). \note Derivatives wrt. both arguments are implemented \ingroup special_functions */ template Type besselI(Type x, Type nu){ Type ans; if(CppAD::Variable(nu)) { CppAD::vector tx(3); tx[0] = x; tx[1] = nu; tx[2] = 0; ans = atomic::bessel_i(tx)[0]; } else { CppAD::vector tx(2); tx[0] = x; tx[1] = nu; ans = atomic::bessel_i_10(tx)[0]; } return ans; } VECTORIZE2_tt(besselI) /** \brief besselJ function (same as besselJ from R). \note Derivatives wrt. both arguments are implemented \ingroup special_functions */ template Type besselJ(Type x, Type nu){ CppAD::vector tx(3); tx[0] = x; tx[1] = nu; tx[2] = 0; Type ans = atomic::bessel_j(tx)[0]; return ans; } VECTORIZE2_tt(besselJ) /** \brief besselY function (same as besselY from R). \note Derivatives wrt. both arguments are implemented \ingroup special_functions */ template Type besselY(Type x, Type nu){ CppAD::vector tx(3); tx[0] = x; tx[1] = nu; tx[2] = 0; Type ans = atomic::bessel_y(tx)[0]; return ans; } VECTORIZE2_tt(besselY) /** \brief dtweedie function (same as dtweedie.series from R package 'tweedie'). Silently returns NaN if not within the valid parameter range: \f[ (0 \leq y) \land (0 < \mu) \land (0 < \phi) \land (1 < p) \land (p < 2) \f] . This implementation can be used for both constant and variable y. However, note that the derivative wrt. y is hardcoded to return zero (!). \note Parameter order differs from the R version. \warning The derivative wrt. the y argument is disabled (zero). Hence the tweedie distribution can only be used for *data* (not random effects). \ingroup R_style_distribution */ template Type dtweedie(Type y, Type mu, Type phi, Type p, int give_log = 0) { Type p1 = p - 1.0, p2 = 2.0 - p; Type ans = -pow(mu, p2) / (phi * p2); // log(prob(y=0)) if (y > 0 || CppAD::Variable(y)) { CppAD::vector tx(4); tx[0] = y; tx[1] = phi; tx[2] = p; tx[3] = 0; Type ans2 = atomic::tweedie_logW(tx)[0]; ans2 += -y / (phi * p1 * pow(mu, p1)) - log(y); if (CppAD::Variable(y)) { ans += CppAD::CondExpGt(y, Type(0), ans2, Type(0)); } else { ans += ans2; } } return ( give_log ? ans : exp(ans) ); } VECTORIZE5_tttti(dtweedie) /** \brief Conway-Maxwell-Poisson log normalizing constant. \f[ Z(\lambda, \nu) = \sum_{i=0}^{\infty} \frac{\lambda^i}{(i!)^\nu} \f] . \param loglambda \f$ \log(\lambda) \f$ \param nu \f$ \nu \f$ \return \f$ \log Z(\lambda, \nu) \f$ */ template Type compois_calc_logZ(Type loglambda, Type nu) { CppAD::vector tx(3); tx[0] = loglambda; tx[1] = nu; tx[2] = 0; return atomic::compois_calc_logZ(tx)[0]; } VECTORIZE2_tt(compois_calc_logZ) /** \brief Conway-Maxwell-Poisson. Calculate log(lambda) from log(mean). \param logmean \f$ \log(E[X]) \f$ \param nu \f$ \nu \f$ \return \f$ \log \lambda \f$ */ template Type compois_calc_loglambda(Type logmean, Type nu) { CppAD::vector tx(3); tx[0] = logmean; tx[1] = nu; tx[2] = 0; return atomic::compois_calc_loglambda(tx)[0]; } VECTORIZE2_tt(compois_calc_loglambda) /** \brief Conway-Maxwell-Poisson. Calculate density. \f[ P(X=x) \propto \frac{\lambda^x}{(x!)^\nu}\:,x=0,1,\ldots \f] Silently returns NaN if not within the valid parameter range: \f[ (0 \leq x) \land (0 < \lambda) \land (0 < \nu) \f] . \param x Observation \param mode Approximate mode \f$ \lambda^\frac{1}{\nu} \f$ \param nu \f$ \nu \f$ \ingroup R_style_distribution */ template T1 dcompois(T1 x, T2 mode, T3 nu, int give_log = 0) { T2 loglambda = nu * log(mode); T1 ans = x * loglambda - nu * lfactorial(x); ans -= compois_calc_logZ(loglambda, nu); return ( give_log ? ans : exp(ans) ); } /** \brief Conway-Maxwell-Poisson. Calculate density parameterized via the mean. Silently returns NaN if not within the valid parameter range: \f[ (0 \leq x) \land (0 < E[X]) \land (0 < \nu) \f] . \param x Observation \param mean \f$ E[X] \f$ \param nu \f$ \nu \f$ \ingroup R_style_distribution */ template T1 dcompois2(T1 x, T2 mean, T3 nu, int give_log = 0) { T2 logmean = log(mean); T2 loglambda = compois_calc_loglambda(logmean, nu); T1 ans = x * loglambda - nu * lfactorial(x); ans -= compois_calc_logZ(loglambda, nu); return ( give_log ? ans : exp(ans) ); } /********************************************************************/ /* SIMULATON CODE */ /********************************************************************/ extern "C" { double Rf_rnorm(double mu, double sigma); } /** \brief Simulate from a normal distribution */ template Type rnorm(Type mu, Type sigma) { return Rf_rnorm(asDouble(mu), asDouble(sigma)); } VECTORIZE2_tt(rnorm) VECTORIZE2_n(rnorm) extern "C" { double Rf_rpois(double mu); } /** \brief Simulate from a Poisson distribution */ template Type rpois(Type mu) { return Rf_rpois(asDouble(mu)); } VECTORIZE1_t(rpois) VECTORIZE1_n(rpois) extern "C" { double Rf_runif(double a, double b); } /** \brief Simulate from a uniform distribution */ template Type runif(Type a, Type b) { return Rf_runif(asDouble(a), asDouble(b)); } VECTORIZE2_tt(runif) VECTORIZE2_n(runif) extern "C" { double Rf_rbinom(double size, double prob); } /** \brief Simulate from a binomial distribution */ template Type rbinom(Type size, Type prob) { return Rf_rbinom(asDouble(size), asDouble(prob)); } VECTORIZE2_tt(rbinom) VECTORIZE2_n(rbinom) extern "C" { double Rf_rgamma(double shape, double scale); } /** \brief Simulate from a gamma distribution */ template Type rgamma(Type shape, Type scale) { return Rf_rgamma(asDouble(shape), asDouble(scale)); } VECTORIZE2_tt(rgamma) VECTORIZE2_n(rgamma) extern "C" { double Rf_rexp(double rate); } /** \brief Simulate from an exponential distribution */ template Type rexp(Type rate) { return Rf_rexp(asDouble(rate)); } VECTORIZE1_t(rexp) VECTORIZE1_n(rexp) extern "C" { double Rf_rbeta(double shape1, double shape2); } /** \brief Simulate from a beta distribution */ template Type rbeta(Type shape1, Type shape2) { return Rf_rbeta(asDouble(shape1), asDouble(shape2)); } VECTORIZE2_tt(rbeta) VECTORIZE2_n(rbeta) extern "C" { double Rf_rf(double df1, double df2); } /** \brief Simulate from an F distribution */ template Type rf(Type df1, Type df2) { return Rf_rf(asDouble(df1), asDouble(df2)); } VECTORIZE2_tt(rf) VECTORIZE2_n(rf) extern "C" { double Rf_rlogis(double location, double scale); } /** \brief Simulate from a logistic distribution */ template Type rlogis(Type location, Type scale) { return Rf_rlogis(asDouble(location), asDouble(scale)); } VECTORIZE2_tt(rlogis) VECTORIZE2_n(rlogis) extern "C" { double Rf_rt(double df); } /** \brief Simulate from a Student's t distribution */ template Type rt(Type df) { return Rf_rt(asDouble(df)); } VECTORIZE1_t(rt) VECTORIZE1_n(rt) extern "C" { double Rf_rweibull(double shape, double scale); } /** \brief Simulate from a Weibull distribution */ template Type rweibull(Type shape, Type scale) { return Rf_rweibull(asDouble(shape), asDouble(scale)); } VECTORIZE2_tt(rweibull) VECTORIZE2_n(rweibull) /** \brief Simulate from a Conway-Maxwell-Poisson distribution */ template Type rcompois(Type mode, Type nu) { Type loglambda = nu * log(mode); return atomic::compois_utils::simulate(asDouble(loglambda), asDouble(nu)); } VECTORIZE2_tt(rcompois) VECTORIZE2_n(rcompois) /** \brief Simulate from a Conway-Maxwell-Poisson distribution */ template Type rcompois2(Type mean, Type nu) { Type logmean = log(mean); Type loglambda = compois_calc_loglambda(logmean, nu); return atomic::compois_utils::simulate(asDouble(loglambda), asDouble(nu)); } VECTORIZE2_tt(rcompois2) // Note: Vectorize manually to avoid many identical calls to // 'calc_loglambda'. template vector rcompois2(int n, Type mean, Type nu) { Type logmean = log(mean); Type loglambda = compois_calc_loglambda(logmean, nu); Type mode = exp(loglambda / nu); return rcompois(n, mode, nu); } /** \brief Simulate from tweedie distribution */ template Type rtweedie(Type mu, Type phi, Type p) { // Copied from R function tweedie::rtweedie Type lambda = pow(mu, 2. - p) / (phi * (2. - p)); Type alpha = (2. - p) / (1. - p); Type gam = phi * (p - 1.) * pow(mu, p - 1.); Type N = rpois(lambda); Type ans = rgamma( -alpha * N /* shape */, gam /* scale */); return ans; } VECTORIZE3_ttt(rtweedie) VECTORIZE3_n(rtweedie) TMB/inst/include/cppad/0000755000176200001440000000000014536067013014370 5ustar liggesusersTMB/inst/include/cppad/SpeedTest.h0000644000176200001440000000005414113627761016443 0ustar liggesusers/* $Id$ */ # include "cppad/speed_test.hpp" TMB/inst/include/cppad/elapsed_seconds.hpp0000644000176200001440000001161014536067012020232 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ELAPSED_SECONDS_INCLUDED # define CPPAD_ELAPSED_SECONDS_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin elapsed_seconds$$ $spell Microsoft gettimeofday std chrono $$ $section Returns Elapsed Number of Seconds$$ $index elapsed_seconds$$ $index seconds, time$$ $index time, seconds$$ $head Syntax$$ $icode%s% = elapsed_seconds()%$$ $head Purpose$$ This routine is accurate to within .02 seconds (see $cref elapsed_seconds.cpp$$). It does not necessary work for time intervals that are greater than a day. $list number$$ If the C++11 $code std::chrono::high_resolution_clock$$ is available, it will be used for timing. $lnext Otherwise, if running under the Microsoft compiler, $code ::GetSystemTime$$ will be used for timing. $lnext Otherwise, if $code gettimeofday$$ is available, it is used for timing. $lnext Otherwise, $code std::clock()$$ will be used for timing. $lend $head s$$ is a $code double$$ equal to the number of seconds since the first call to $code elapsed_seconds$$. $head Microsoft Systems$$ It you are using $code ::GetSystemTime$$, you will need to link in the external routine called $cref microsoft_timer$$. $children% speed/example/elapsed_seconds.cpp %$$ $head Example$$ The routine $cref elapsed_seconds.cpp$$ is an example and test of this routine. $end ----------------------------------------------------------------------- */ // For some unknown reason under Fedora (which needs to be understood), // if you move this include for cppad_assert.hpp below include for define.hpp, // cd work/speed/example // make test.sh // fails with the error message 'gettimeofday' not defined. # include // define CPPAD_NULL # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include # if CPPAD_HAS_HIGH_RESOLUTION_CLOCK # include # elif _MSC_VER extern double microsoft_timer(void); # elif CPPAD_HAS_GETTIMEOFDAY # include # else # include # endif namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file elapsed_seconds.hpp \brief Function that returns the elapsed seconds from first call. */ /*! Returns the elapsed number since the first call to this function. This routine tries is accurate to within .02 seconds. It does not necessary work for time intervals that are less than a day. \li If running under the Microsoft system, it uses \c ::%GetSystemTime for timing. \li Otherwise, if \c gettimeofday is available, it is used. \li Otherwise, \c std::clock() is used. \return The number of seconds since the first call to \c elapsed_seconds. */ inline double elapsed_seconds(void) // -------------------------------------------------------------------------- # if CPPAD_HAS_HIGH_RESOLUTION_CLOCK { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static bool first_ = true; static std::chrono::time_point start_; if( first_ ) { start_ = std::chrono::high_resolution_clock::now(); first_ = false; return 0.0; } std::chrono::time_point now; now = std::chrono::high_resolution_clock::now(); std::chrono::duration difference = now - start_; return difference.count(); } // -------------------------------------------------------------------------- # elif _MSC_VER { return microsoft_timer(); } // -------------------------------------------------------------------------- # elif CPPAD_HAS_GETTIMEOFDAY { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static bool first_ = true; static struct timeval tv_; struct timeval tv; if( first_ ) { gettimeofday(&tv_, CPPAD_NULL); first_ = false; return 0.; } gettimeofday(&tv, CPPAD_NULL); assert( tv.tv_sec >= tv_.tv_sec ); double sec = double(tv.tv_sec - tv_.tv_sec); double usec = double(tv.tv_usec) - double(tv_.tv_usec); double diff = sec + 1e-6*usec; return diff; } // -------------------------------------------------------------------------- # else // Not CPPAD_HAS_HIGH_RESOLUTION_CLOCK or CPPAD_HAS_GETTIMEOFDAY { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static bool first_ = true; static double tic_; double tic; if( first_ ) { tic_ = double(std::clock()); first_ = false; return 0.; } tic = double( std::clock() ); double diff = (tic - tic_) / double(CLOCKS_PER_SEC); return diff; } # endif // -------------------------------------------------------------------------- } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/nan.hpp0000644000176200001440000001052014536067012015652 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_NAN_INCLUDED # define CPPAD_NAN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin nan$$ $spell hasnan cppad hpp CppAD isnan bool const $$ $section Obtain Nan or Determine if a Value is Nan$$ $index isnan$$ $index hasnan$$ $index nan$$ $head Syntax$$ $codei%# include %$$ $icode%s% = nan(%z%) %$$ $icode%b% = isnan(%s%) %$$ $icode%b% = hasnan(%v%)%$$ $head Purpose$$ It obtain and check for the value not a number $code nan$$. The IEEE standard specifies that a floating point value $icode a$$ is $code nan$$ if and only if the following returns true $codei% %a% != %a% %$$ $head Include$$ The file $code cppad/nan.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $subhead Macros$$ $index macro, nan$$ $index macro, isnan$$ $index nan, macro$$ $index isnan, macro$$ Some C++ compilers use preprocessor symbols called $code nan$$ and $code isnan$$. These preprocessor symbols will no longer be defined after this file is included. $head nan$$ This routine returns a $code nan$$ with the same type as $icode z$$. $subhead z$$ The argument $icode z$$ has prototype $codei% const %Scalar% &%z% %$$ and its value is zero (see $cref/Scalar/nan/Scalar/$$ for the definition of $icode Scalar$$). $subhead s$$ The return value $icode s$$ has prototype $codei% %Scalar% %s% %$$ It is the value $code nan$$ for this floating point type. $head isnan$$ This routine determines if a scalar value is $code nan$$. $subhead s$$ The argument $icode s$$ has prototype $codei% const %Scalar% %s% %$$ $subhead b$$ The return value $icode b$$ has prototype $codei% bool %b% %$$ It is true if the value $icode s$$ is $code nan$$. $head hasnan$$ This routine determines if a $cref SimpleVector$$ has an element that is $code nan$$. $subhead v$$ The argument $icode v$$ has prototype $codei% const %Vector% &%v% %$$ (see $cref/Vector/nan/Vector/$$ for the definition of $icode Vector$$). $subhead b$$ The return value $icode b$$ has prototype $codei% bool %b% %$$ It is true if the vector $icode v$$ has a $code nan$$. $head Scalar$$ The type $icode Scalar$$ must support the following operations; $table $bold Operation$$ $cnext $bold Description$$ $rnext $icode%a% / %b%$$ $cnext division operator (returns a $icode Scalar$$ object) $rnext $icode%a% == %b%$$ $cnext equality operator (returns a $code bool$$ object) $rnext $icode%a% != %b%$$ $cnext not equality operator (returns a $code bool$$ object) $tend Note that the division operator will be used with $icode a$$ and $icode b$$ equal to zero. For some types (e.g. $code int$$) this may generate an exception. No attempt is made to catch any such exception. $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with elements of type $icode Scalar$$. $children% example/nan.cpp %$$ $head Example$$ The file $cref nan.cpp$$ contains an example and test of this routine. It returns true if it succeeds and false otherwise. $end */ # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include /* # define nan There must be a define for every CppAD undef */ # ifdef nan # undef nan # endif /* # define isnan There must be a define for every CppAD undef */ # ifdef isnan # undef isnan # endif namespace CppAD { // BEGIN CppAD namespace template inline Scalar nan(const Scalar &zero) { return zero / zero; } template inline bool isnan(const Scalar &s) { return (s != s); } template bool hasnan(const Vector &v) { bool found_nan; size_t i; i = v.size(); found_nan = false; // on MS Visual Studio 2012, CppAD required in front of isnan ? while(i--) found_nan |= CppAD::isnan(v[i]); return found_nan; } } // End CppAD namespace # endif TMB/inst/include/cppad/example/0000755000176200001440000000000014536067013016023 5ustar liggesusersTMB/inst/include/cppad/example/base_adolc.hpp0000644000176200001440000001614614536067013020620 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BASE_ADOLC_INCLUDED # define CPPAD_BASE_ADOLC_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin base_adolc.hpp$$ $spell erf ifndef define endif Rel codassign eps std abs_geq fabs cppad.hpp undef Lt Le Eq Ge Gt namespace cassert condassign hpp bool const Adolc adouble CondExpOp inline enum CppAD pow acos asin atan cos cosh exp sqrt $$ $index Adolc, adouble as Base$$ $index Base, Adolc's adouble$$ $index adouble, as Base$$ $section Enable use of AD where Base is Adolc's adouble Type$$ $head Syntax$$ $codei%# include %$$ $children% example/mul_level_adolc.cpp %$$ $head Example$$ The file $cref mul_level_adolc.cpp$$ contains an example use of Adolc's $code adouble$$ type for a CppAD $icode Base$$ type. It returns true if it succeeds and false otherwise. The file $cref mul_level_adolc_ode.cpp$$ contains a more realistic (and complex) example. $head Include Files$$ This file $code base_adolc.hpp$$ requires $code adouble$$ to be defined. In addition, it is included before $code $$, but it needs to include parts of CppAD that are used by this file. This is done with the following include commands: $codep */ # include # include /* $$ $head CondExpOp$$ The type $code adouble$$ supports a conditional assignment function with the syntax $codei% condassign(%a%, %b%, %c%, %d%) %$$ which evaluates to $codei% %a% = (%b% > 0) ? %c% : %d%; %$$ This enables one to include conditionals in the recording of $code adouble$$ operations and later evaluation for different values of the independent variables (in the same spirit as the CppAD $cref CondExp$$ function). $codep */ namespace CppAD { inline adouble CondExpOp( enum CppAD::CompareOp cop , const adouble &left , const adouble &right , const adouble &trueCase , const adouble &falseCase ) { adouble result; switch( cop ) { case CompareLt: // left < right condassign(result, right - left, trueCase, falseCase); break; case CompareLe: // left <= right condassign(result, left - right, falseCase, trueCase); break; case CompareEq: // left == right condassign(result, left - right, falseCase, trueCase); condassign(result, right - left, falseCase, result); break; case CompareGe: // left >= right condassign(result, right - left, falseCase, trueCase); break; case CompareGt: // left > right condassign(result, left - right, trueCase, falseCase); break; default: CppAD::ErrorHandler::Call( true , __LINE__ , __FILE__ , "CppAD::CondExp", "Error: for unknown reason." ); result = trueCase; } return result; } } /* $$ $head EqualOpSeq$$ The Adolc user interface does not specify a way to determine if two $code adouble$$ variables correspond to the same operations sequence. Make $code EqualOpSeq$$ an error if it gets used: $codep */ namespace CppAD { inline bool EqualOpSeq(const adouble &x, const adouble &y) { CppAD::ErrorHandler::Call( true , __LINE__ , __FILE__ , "CppAD::EqualOpSeq(x, y)", "Error: adouble does not support EqualOpSeq." ); return false; } } /* $$ $head Identical$$ The Adolc user interface does not specify a way to determine if an $code adouble$$ depends on the independent variables. To be safe (but slow) return $code false$$ in all the cases below. $codep */ namespace CppAD { inline bool IdenticalPar(const adouble &x) { return false; } inline bool IdenticalZero(const adouble &x) { return false; } inline bool IdenticalOne(const adouble &x) { return false; } inline bool IdenticalEqualPar(const adouble &x, const adouble &y) { return false; } } /* $$ $head Integer$$ $codep */ inline int Integer(const adouble &x) { return static_cast( x.getValue() ); } /* $$ $head Ordered$$ $codep */ namespace CppAD { inline bool GreaterThanZero(const adouble &x) { return (x > 0); } inline bool GreaterThanOrZero(const adouble &x) { return (x >= 0); } inline bool LessThanZero(const adouble &x) { return (x < 0); } inline bool LessThanOrZero(const adouble &x) { return (x <= 0); } inline bool abs_geq(const adouble& x, const adouble& y) { return fabs(x) >= fabs(y); } } /* $$ $head Unary Standard Math$$ The following $cref/required/base_require/$$ functions are defined by the Adolc package for the $code adouble$$ base case: $pre $$ $code acos$$, $code asin$$, $code atan$$, $code cos$$, $code cosh$$, $code exp$$, $code fabs$$, $code log$$, $code sin$$, $code sinh$$, $code sqrt$$, $code tan$$. $head erf$$ If the error function is supported by the compiler, it must also be supported by a $icode Base$$ type; see $cref/erf/base_std_math/erf/$$. The adolc package does not support this function: $codep */ namespace CppAD { # if CPPAD_COMPILER_HAS_ERF inline adouble erf(const adouble& x) { CPPAD_ASSERT_KNOWN( false, "erf: adolc does not support the error function" ); return 0; } # endif } /* $$ $head sign$$ This $cref/required/base_require/$$ function is defined using the $code codassign$$ function so that its $code adouble$$ operation sequence does not depend on the value of $icode x$$. $codep */ namespace CppAD { inline adouble sign(const adouble& x) { adouble s_plus, s_minus, half(.5); // set s_plus to sign(x)/2, except for case x == 0, s_plus = -.5 condassign(s_plus, +x, -half, +half); // set s_minus to -sign(x)/2, except for case x == 0, s_minus = -.5 condassign(s_minus, -x, -half, +half); // set s to sign(x) return s_plus - s_minus; } } /* $$ $head abs$$ This $cref/required/base_require/$$ function uses the adolc $code fabs$$ function: $codep */ namespace CppAD { inline adouble abs(const adouble& x) { return fabs(x); } } /* $$ $head pow$$ This $cref/required/base_require/$$ function is defined by the Adolc package for the $code adouble$$ base case. $head limits$$ The following defines the numeric limits functions $code epsilon$$, $code min$$, and $code max$$ for the type $code adouble$$. It also defines the deprecated $code epsilon$$ function: $codep */ namespace CppAD { template <> class numeric_limits { public: // machine epsilon static adouble epsilon(void) { return adouble( std::numeric_limits::epsilon() ); } // minimum positive normalized value static adouble min(void) { return adouble( std::numeric_limits::min() ); } // maximum finite value static adouble max(void) { return adouble( std::numeric_limits::max() ); } }; // deprecated machine epsilon template <> inline adouble epsilon(void) { return numeric_limits::epsilon(); } } /* $$ $end */ # endif TMB/inst/include/cppad/example/matrix_mul.hpp0000644000176200001440000003563214536067013020726 0ustar liggesusers// $Id$ # ifndef CPPAD_MATRIX_MUL_INCLUDED # define CPPAD_MATRIX_MUL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin atomic_matrix_mul.hpp$$ $spell $$ $section Matrix Multiply as an Atomic Operation$$ $index multiply, matrix atomic operation$$ $index atomic, matrix multiply operation$$ $index matrix, multiply atomic operation$$ $nospell $head Start Class Definition$$ $codep */ # include namespace { // Begin empty namespace using CppAD::vector; // void my_union( std::set& result , const std::set& left , const std::set& right ) { std::set temp; std::set_union( left.begin() , left.end() , right.begin() , right.end() , std::inserter(temp, temp.begin()) ); result.swap(temp); } // // matrix result = left * right class matrix_mul : public CppAD::atomic_base { /* $$ $head Constructor$$ $codep */ private: // number of rows in left operand and in the result const size_t nr_result_; // number of columns in left operand and rows in right operand const size_t n_middle_; // number of columns in right operand and in the result const size_t nc_result_; // dimension of the domain space const size_t n_; // dimension of the range space # ifndef NDEBUG const size_t m_; # endif public: // --------------------------------------------------------------------- // constructor matrix_mul(size_t nr_result, size_t n_middle, size_t nc_result) : CppAD::atomic_base("matrix_mul"), nr_result_(nr_result) , n_middle_(n_middle) , nc_result_(nc_result) , n_( nr_result * n_middle + n_middle * nc_result ) # ifndef NDEBUG , m_( n_middle * nc_result ) # endif { } private: /* $$ $head Left Operand Element Index$$ $codep */ // left matrix element index in the taylor coefficient vector tx. size_t left( size_t i , // left matrix row index size_t j , // left matrix column index size_t k , // Taylor coeffocient order size_t nk ) // number of Taylor coefficients in tx { assert( i < nr_result_ ); assert( j < n_middle_ ); return (i * n_middle_ + j) * nk + k; } /* $$ $head Right Operand Element Index$$ $codep */ // right matrix element index in the taylor coefficient vector tx. size_t right( size_t i , // right matrix row index size_t j , // right matrix column index size_t k , // Taylor coeffocient order size_t nk ) // number of Taylor coefficients in tx { assert( i < n_middle_ ); assert( j < nc_result_ ); size_t offset = nr_result_ * n_middle_; return (offset + i * nc_result_ + j) * nk + k; } /* $$ $head Result Element Index$$ $codep */ // result matrix element index in the taylor coefficient vector ty. size_t result( size_t i , // result matrix row index size_t j , // result matrix column index size_t k , // Taylor coeffocient order size_t nk ) // number of Taylor coefficients in ty { assert( i < nr_result_ ); assert( j < nc_result_ ); return (i * nc_result_ + j) * nk + k; } /* $$ $head Forward Matrix Multipliy$$ $codep */ // Forward mode multiply Taylor coefficients in tx and sum into ty // (for one pair of left and right orders) void forward_multiply( size_t k_left , // order for left coefficients size_t k_right , // order for right coefficients const vector& tx , // domain space Taylor coefficients vector& ty ) // range space Taylor coefficients { size_t nk = tx.size() / n_; assert( nk == ty.size() / m_ ); // size_t k_result = k_left + k_right; assert( k_result < nk ); // for(size_t i = 0; i < nr_result_; i++) { for(size_t j = 0; j < nc_result_; j++) { double sum = 0.0; for(size_t ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k_left, nk); size_t i_right = right(ell, j, k_right, nk); sum += tx[i_left] * tx[i_right]; } size_t i_result = result(i, j, k_result, nk); ty[i_result] += sum; } } } /* $$ $head Reverse Matrix Multipliy$$ $codep */ // Reverse mode partials of Taylor coefficients and sum into px // (for one pair of left and right orders) void reverse_multiply( size_t k_left , // order for left coefficients size_t k_right , // order for right coefficients const vector& tx , // domain space Taylor coefficients const vector& ty , // range space Taylor coefficients vector& px , // partials w.r.t. tx const vector& py ) // partials w.r.t. ty { size_t nk = tx.size() / n_; assert( nk == ty.size() / m_ ); assert( tx.size() == px.size() ); assert( ty.size() == py.size() ); // size_t k_result = k_left + k_right; assert( k_result < nk ); // for(size_t i = 0; i < nr_result_; i++) { for(size_t j = 0; j < nc_result_; j++) { size_t i_result = result(i, j, k_result, nk); for(size_t ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k_left, nk); size_t i_right = right(ell, j, k_right, nk); // sum += tx[i_left] * tx[i_right]; px[i_left] += tx[i_right] * py[i_result]; px[i_right] += tx[i_left] * py[i_result]; } } } return; } /* $$ $head forward$$ $codep */ // forward mode routine called by CppAD bool forward( size_t q , size_t p , const vector& vx , vector& vy , const vector& tx , vector& ty ) { size_t p1 = p + 1; assert( vx.size() == 0 || n_ == vx.size() ); assert( vx.size() == 0 || m_ == vy.size() ); assert( n_ * p1 == tx.size() ); assert( m_ * p1 == ty.size() ); size_t i, j, ell; // check if we are computing vy information if( vx.size() > 0 ) { size_t nk = 1; size_t k = 0; for(i = 0; i < nr_result_; i++) { for(j = 0; j < nc_result_; j++) { bool var = false; for(ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k, nk); size_t i_right = right(ell, j, k, nk); bool nz_left = vx[i_left] |(tx[i_left] != 0.); bool nz_right = vx[i_right]|(tx[i_right] != 0.); // if not multiplying by the constant zero if( nz_left & nz_right ) var |= vx[i_left] | vx[i_right]; } size_t i_result = result(i, j, k, nk); vy[i_result] = var; } } } // initialize result as zero size_t k; for(i = 0; i < nr_result_; i++) { for(j = 0; j < nc_result_; j++) { for(k = q; k <= p; k++) ty[ result(i, j, k, p1) ] = 0.0; } } for(k = q; k <= p; k++) { // sum the produces that result in order k for(ell = 0; ell <= k; ell++) forward_multiply(ell, k - ell, tx, ty); } // all orders are implented, so always return true return true; } /* $$ $head reverse$$ $codep */ // reverse mode routine called by CppAD virtual bool reverse( size_t p , const vector& tx , const vector& ty , vector& px , const vector& py ) { size_t p1 = p + 1; assert( n_ * p1 == tx.size() ); assert( m_ * p1 == ty.size() ); assert( px.size() == tx.size() ); assert( py.size() == ty.size() ); // initialize summation for(size_t i = 0; i < px.size(); i++) px[i] = 0.0; // number of orders to differentiate size_t k = p1; while(k--) { // differentiate the produces that result in order k for(size_t ell = 0; ell <= k; ell++) reverse_multiply(ell, k - ell, tx, ty, px, py); } // all orders are implented, so always return true return true; } /* $$ $head for_sparse_jac$$ $codep */ // forward Jacobian sparsity routine called by CppAD virtual bool for_sparse_jac( size_t q , const vector& r , vector& s ) { assert( n_ * q == r.size() ); assert( m_ * q == s.size() ); size_t p; // sparsity for S(x) = f'(x) * R size_t nk = 1; size_t k = 0; for(size_t i = 0; i < nr_result_; i++) { for(size_t j = 0; j < nc_result_; j++) { size_t i_result = result(i, j, k, nk); for(p = 0; p < q; p++) s[i_result * q + p] = false; for(size_t ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k, nk); size_t i_right = right(ell, j, k, nk); for(p = 0; p < q; p++) { s[i_result * q + p] |= r[i_left * q + p ]; s[i_result * q + p] |= r[i_right * q + p ]; } } } } return true; } virtual bool for_sparse_jac( size_t q , const vector< std::set >& r , vector< std::set >& s ) { assert( n_ == r.size() ); assert( m_ == s.size() ); // sparsity for S(x) = f'(x) * R size_t nk = 1; size_t k = 0; for(size_t i = 0; i < nr_result_; i++) { for(size_t j = 0; j < nc_result_; j++) { size_t i_result = result(i, j, k, nk); s[i_result].clear(); for(size_t ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k, nk); size_t i_right = right(ell, j, k, nk); // my_union( s[i_result], s[i_result], r[i_left] ); my_union( s[i_result], s[i_result], r[i_right] ); } } } return true; } /* $$ $head rev_sparse_jac$$ $codep */ // reverse Jacobian sparsity routine called by CppAD virtual bool rev_sparse_jac( size_t q , const vector& rt , vector& st ) { assert( n_ * q == st.size() ); assert( m_ * q == rt.size() ); size_t i, j, p; // initialize for(i = 0; i < n_; i++) { for(p = 0; p < q; p++) st[ i * q + p ] = false; } // sparsity for S(x)^T = f'(x)^T * R^T size_t nk = 1; size_t k = 0; for(i = 0; i < nr_result_; i++) { for(j = 0; j < nc_result_; j++) { size_t i_result = result(i, j, k, nk); for(size_t ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k, nk); size_t i_right = right(ell, j, k, nk); for(p = 0; p < q; p++) { st[i_left * q + p] |= rt[i_result * q + p]; st[i_right* q + p] |= rt[i_result * q + p]; } } } } return true; } virtual bool rev_sparse_jac( size_t q , const vector< std::set >& rt , vector< std::set >& st ) { assert( n_ == st.size() ); assert( m_ == rt.size() ); size_t i, j; // initialize for(i = 0; i < n_; i++) st[i].clear(); // sparsity for S(x)^T = f'(x)^T * R^T size_t nk = 1; size_t k = 0; for(i = 0; i < nr_result_; i++) { for(j = 0; j < nc_result_; j++) { size_t i_result = result(i, j, k, nk); for(size_t ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k, nk); size_t i_right = right(ell, j, k, nk); // my_union(st[i_left], st[i_left], rt[i_result]); my_union(st[i_right], st[i_right], rt[i_result]); } } } return true; } /* $$ $head rev_sparse_hes$$ $codep */ // reverse Hessian sparsity routine called by CppAD virtual bool rev_sparse_hes( const vector& vx, const vector& s , vector& t , size_t q , const vector< std::set >& r , const vector< std::set >& u , vector< std::set >& v ) { size_t n = vx.size(); assert( t.size() == n ); assert( r.size() == n ); assert( v.size() == n ); # ifndef NDEBUG size_t m = s.size(); assert( u.size() == m ); # endif size_t i, j; // // initilaize sparsity patterns as false for(j = 0; j < n; j++) { t[j] = false; v[j].clear(); } size_t nk = 1; size_t k = 0; for(i = 0; i < nr_result_; i++) { for(j = 0; j < nc_result_; j++) { size_t i_result = result(i, j, k, nk); for(size_t ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k, nk); size_t i_right = right(ell, j, k, nk); // // Compute sparsity for T(x) = S(x) * f'(x). // We need not use vx with f'(x) back propagation. t[i_left] |= s[i_result]; t[i_right] |= s[i_result]; // V(x) = f'(x)^T * U(x) + S(x) * f''(x) * R // U(x) = g''(y) * f'(x) * R // S(x) = g'(y) // back propagate f'(x)^T * U(x) // (no need to use vx with f'(x) propogation) my_union(v[i_left], v[i_left], u[i_result] ); my_union(v[i_right], v[i_right], u[i_result] ); // back propagate S(x) * f''(x) * R // (here is where we must check for cross terms) if( s[i_result] & vx[i_left] & vx[i_right] ) { my_union(v[i_left], v[i_left], r[i_right] ); my_union(v[i_right], v[i_right], r[i_left] ); } } } } return true; } virtual bool rev_sparse_hes( const vector& vx, const vector& s , vector& t , size_t q , const vector& r , const vector& u , vector& v ) { size_t n = vx.size(); assert( t.size() == n ); assert( r.size() == n * q ); assert( v.size() == n * q ); # ifndef NDEBUG size_t m = s.size(); assert( u.size() == m * q ); # endif size_t i, j, p; // // initilaize sparsity patterns as false for(j = 0; j < n; j++) { t[j] = false; for(p = 0; p < q; p++) v[j * q + p] = false; } size_t nk = 1; size_t k = 0; for(i = 0; i < nr_result_; i++) { for(j = 0; j < nc_result_; j++) { size_t i_result = result(i, j, k, nk); for(size_t ell = 0; ell < n_middle_; ell++) { size_t i_left = left(i, ell, k, nk); size_t i_right = right(ell, j, k, nk); // // Compute sparsity for T(x) = S(x) * f'(x). // We so not need to use vx with f'(x) propagation. t[i_left] |= s[i_result]; t[i_right] |= s[i_result]; // V(x) = f'(x)^T * U(x) + S(x) * f''(x) * R // U(x) = g''(y) * f'(x) * R // S(x) = g'(y) // back propagate f'(x)^T * U(x) // (no need to use vx with f'(x) propogation) for(p = 0; p < q; p++) { v[ i_left * q + p] |= u[ i_result * q + p]; v[ i_right * q + p] |= u[ i_result * q + p]; } // back propagate S(x) * f''(x) * R // (here is where we must check for cross terms) if( s[i_result] & vx[i_left] & vx[i_right] ) { for(p = 0; p < q; p++) { v[i_left * q + p] |= r[i_right * q + p]; v[i_right * q + p] |= r[i_left * q + p]; } } } } } return true; } /* $$ $head End Class Definition$$ $codep */ }; // End of matrix_mul class } // End empty namespace /* $$ $$ $comment end nospell$$ $end */ # endif TMB/inst/include/cppad/example/cppad_eigen.hpp0000644000176200001440000001147314536067013021000 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_CPPAD_EIGEN_INCLUDED # define CPPAD_CPPAD_EIGEN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin cppad_eigen.hpp$$ $spell impl typename Real Real inline neg eps plugin atan Num acos asin CppAD std::numeric enum Mul Eigen cppad.hpp namespace struct typedef const imag sqrt exp cos $$ $section Enable Use of Eigen Linear Algebra Package with CppAD$$ $head Syntax$$ $codei%# include %$$ $children% cppad/example/eigen_plugin.hpp% example/eigen_array.cpp% example/eigen_det.cpp %$$ $head Purpose$$ Enables the use of the $href%http://eigen.tuxfamily.org%eigen%$$ linear algebra package with the type $icode%AD<%Base%>%$$. $head Example$$ The files $cref eigen_array.cpp$$ and $cref eigen_det.cpp$$ contain an example and test of this include file. It returns true if it succeeds and false otherwise. $head Include Files$$ The file $code cppad_eigen.hpp$$ includes both $code $$ and $code $$. In addition, The file $cref eigen_plugin.hpp$$ is used to define $code value_type$$ in the Eigen matrix class definition so its vectors are $cref/simple vectors/SimpleVector/$$. $codep */ # define EIGEN_MATRIXBASE_PLUGIN # include # include /* $$ $head Eigen NumTraits$$ Eigen needs the following definitions to work properly with $codei%AD<%Base%>%$$ scalars: $codep */ namespace Eigen { template struct NumTraits< CppAD::AD > : NumTraits { // type that corresponds to the real part of an AD value typedef CppAD::AD Real; // type for AD operations that result in non-integer values typedef CppAD::AD NonInteger; // type for nested value inside an AD expression tree typedef CppAD::AD Nested; typedef CppAD::AD Literal; enum { // does not support complex Base types IsComplex = 0 , // does not support integer Base types IsInteger = 0 , // only support signed Base types IsSigned = 1 , // must initialize an AD object RequireInitialization = 1 , // computational cost of the corresponding operations ReadCost = 1 , AddCost = 2 , MulCost = 2 }; // machine epsilon with type of real part of x // (use assumption that Base is not complex) static CppAD::AD epsilon(void) { return CppAD::numeric_limits< CppAD::AD >::epsilon(); } // relaxed version of machine epsilon for comparison of different // operations that should result in the same value static CppAD::AD dummy_precision(void) { return 100. * CppAD::numeric_limits< CppAD::AD >::epsilon(); } // minimum normalized positive value static CppAD::AD lowest(void) { return CppAD::numeric_limits< CppAD::AD >::min(); } // maximum finite value static CppAD::AD highest(void) { return CppAD::numeric_limits< CppAD::AD >::max(); } }; } /* $$ $head CppAD Namespace$$ Eigen also needs the following definitions to work properly with $codei%AD<%Base%>%$$ scalars: $codep */ namespace CppAD { // functions that return references template const AD& conj(const AD& x) { return x; } template const AD& real(const AD& x) { return x; } // functions that return values (note abs is defined by cppad.hpp) template AD imag(const AD& x) { return CppAD::AD(0.); } template AD abs2(const AD& x) { return x * x; } } namespace Eigen { namespace internal { // Test if version before 3.3 #if ( ( EIGEN_WORLD_VERSION <= 2 ) || ( EIGEN_WORLD_VERSION == 3 ) && ( EIGEN_MAJOR_VERSION <= 2 ) ) template struct significant_decimals_default_impl< CppAD::AD, false> { typedef CppAD::AD Scalar; typedef typename NumTraits::Real RealScalar; static inline int run() { Scalar neg_log_eps = - log( NumTraits::epsilon() ); int ceil_neg_log_eps = Integer( neg_log_eps ); if( Scalar(ceil_neg_log_eps) < neg_log_eps ) ceil_neg_log_eps++; return ceil_neg_log_eps; } }; #endif } } /* $$ $end */ # endif TMB/inst/include/cppad/example/eigen_plugin.hpp0000644000176200001440000000153014536067013021200 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_EIGEN_PLUGIN_INCLUDED # define CPPAD_EIGEN_PLUGIN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /*$ $begin eigen_plugin.hpp$$ $spell eigen_plugin.hpp typedef $$ $section Source Code for eigen_plugin.hpp$$ $codep */ // Declaration needed so an Eigen vector is a simple vector typedef Scalar value_type; /* $$ $end */ # endif TMB/inst/include/cppad/romberg_one.hpp0000644000176200001440000001223614536067013017403 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ROMBERG_ONE_INCLUDED # define CPPAD_ROMBERG_ONE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin RombergOne$$ $spell cppad.hpp bool const Cpp RombergOne $$ $section One DimensionalRomberg Integration$$ $index integrate, Romberg$$ $index Romberg, Integrate$$ $head Syntax$$ $code # include $$ $pre $$ $icode%r% = RombergOne(%F%, %a%, %b%, %n%, %e%)%$$ $head Description$$ Returns the Romberg integration estimate $latex r$$ for a one dimensional integral $latex \[ r = \int_a^b F(x) {\bf d} x + O \left[ (b - a) / 2^{n-1} \right]^{2(p+1)} \] $$ $head Include$$ The file $code cppad/romberg_one.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head r$$ The return value $icode r$$ has prototype $codei% %Float% %r% %$$ It is the estimate computed by $code RombergOne$$ for the integral above. $head F$$ The object $icode F$$ can be of any type, but it must support the operation $codei% %F%(%x%) %$$ The argument $icode x$$ to $icode F$$ has prototype $codei% const %Float% &%x% %$$ The return value of $icode F$$ is a $icode Float$$ object (see description of $cref/Float/RombergOne/Float/$$ below). $head a$$ The argument $icode a$$ has prototype $codei% const %Float% &%a% %$$ It specifies the lower limit for the integration. $head b$$ The argument $icode b$$ has prototype $codei% const %Float% &%b% %$$ It specifies the upper limit for the integration. $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ A total number of $latex 2^{n-1} + 1$$ evaluations of $icode%F%(%x%)%$$ are used to estimate the integral. $head p$$ The argument $icode p$$ has prototype $codei% size_t %p% %$$ It must be less than or equal $latex n$$ and determines the accuracy order in the approximation for the integral that is returned by $code RombergOne$$. To be specific $latex \[ r = \int_a^b F(x) {\bf d} x + O \left[ (b - a) / 2^{n-1} \right]^{2(p+1)} \] $$ $head e$$ The argument $icode e$$ has prototype $codei% %Float% &%e% %$$ The input value of $icode e$$ does not matter and its output value is an approximation for the error in the integral estimates; i.e., $latex \[ e \approx \left| r - \int_a^b F(x) {\bf d} x \right| \] $$ $head Float$$ The type $icode Float$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, if $icode x$$ and $icode y$$ are $icode Float$$ objects, $codei% %x% < %y% %$$ returns the $code bool$$ value true if $icode x$$ is less than $icode y$$ and false otherwise. $children% example/romberg_one.cpp %$$ $head Example$$ $comment% example/romberg_one.cpp %$$ The file $cref romberg_one.cpp$$ contains an example and test a test of using this routine. It returns true if it succeeds and false otherwise. $head Source Code$$ The source code for this routine is in the file $code cppad/romberg_one.hpp$$. $end */ # include # include # include namespace CppAD { // BEGIN CppAD namespace template Float RombergOne( Fun &F , const Float &a , const Float &b , size_t n , size_t p , Float &e ) { size_t ipow2 = 1; size_t k, i; Float pow2, sum, x; Float zero = Float(0); Float two = Float(2); // check specifications for a NumericType CheckNumericType(); CPPAD_ASSERT_KNOWN( n >= 2, "RombergOne: n must be greater than or equal 2" ); CppAD::vector r(n); // set r[i] = trapazoidal rule with 2^i intervals in [a, b] r[0] = ( F(a) + F(b) ) * (b - a) / two; for(i = 1; i < n; i++) { ipow2 *= 2; // there must be a conversion from int to any numeric type pow2 = Float(int(ipow2)); sum = zero; for(k = 1; k < ipow2; k += 2) { // start = a + (b-a)/pow2, increment = 2*(b-a)/pow2 x = ( (pow2 - Float(int(k))) * a + k * b ) / pow2; sum = sum + F(x); } // combine function evaluations in sum with those in T[i-1] r[i] = r[i-1] / two + sum * (b - a) / pow2; } // now compute the higher order estimates size_t ipow4 = 1; // order of accuract for previous estimate Float pow4, pow4minus; for(i = 0; i < p; i++) { // compute estimate accurate to O[ step^(2*(i+1)) ] // put resutls in r[n-1], r[n-2], ... , r[n-i+1] ipow4 *= 4; pow4 = Float(int(ipow4)); pow4minus = Float(ipow4-1); for(k = n-1; k > i; k--) r[k] = ( pow4 * r[k] - r[k-1] ) / pow4minus; } // error estimate for r[n] e = r[n-1] - r[n-2]; if( e < zero ) e = - e; return r[n-1]; } } // END CppAD namespace # endif TMB/inst/include/cppad/CppAD_vector.h0000644000176200001440000000005014113627761017050 0ustar liggesusers/* $Id$ */ # include "cppad/vector.hpp" TMB/inst/include/cppad/ode_err_control.hpp0000644000176200001440000003731014536067012020263 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ODE_ERR_CONTROL_INCLUDED # define CPPAD_ODE_ERR_CONTROL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin OdeErrControl$$ $spell cppad.hpp nstep maxabs exp scur CppAD xf tf xi smin smax eabs erel ef ta tb xa xb const eb $$ $index OdeErrControl$$ $index ODE, control error$$ $index control, ODE error$$ $index error, control ODE$$ $index differential, ODE error control$$ $index equation, ODE error control$$ $section An Error Controller for ODE Solvers$$ $head Syntax$$ $code # include $$ $pre $$ $icode%xf% = OdeErrControl(%method%, %ti%, %tf%, %xi%, %smin%, %smax%, %scur%, %eabs%, %erel%, %ef% , %maxabs%, %nstep% )%$$ $head Description$$ Let $latex \B{R}$$ denote the real numbers and let $latex F : \B{R} \times \B{R}^n \rightarrow \B{R}^n$$ be a smooth function. We define $latex X : [ti , tf] \rightarrow \B{R}^n$$ by the following initial value problem: $latex \[ \begin{array}{rcl} X(ti) & = & xi \\ X'(t) & = & F[t , X(t)] \end{array} \] $$ The routine $code OdeErrControl$$ can be used to adjust the step size used an arbitrary integration methods in order to be as fast as possible and still with in a requested error bound. $head Include$$ The file $code cppad/ode_err_control.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Notation$$ The template parameter types $cref/Scalar/OdeErrControl/Scalar/$$ and $cref/Vector/OdeErrControl/Vector/$$ are documented below. $head xf$$ The return value $icode xf$$ has the prototype $codei% %Vector% %xf% %$$ (see description of $cref/Vector/OdeErrControl/Vector/$$ below). and the size of $icode xf$$ is equal to $icode n$$. If $icode xf$$ contains not a number $cref nan$$, see the discussion of $cref/step/OdeErrControl/Method/Nan/$$. $head Method$$ The class $icode Method$$ and the object $icode method$$ satisfy the following syntax $codei% %Method% &%method% %$$ The object $icode method$$ must support $code step$$ and $code order$$ member functions defined below: $subhead step$$ The syntax $codei% %method%.step(%ta%, %tb%, %xa%, %xb%, %eb%) %$$ executes one step of the integration method. $codei% %ta% %$$ The argument $icode ta$$ has prototype $codei% const %Scalar% &%ta% %$$ It specifies the initial time for this step in the ODE integration. (see description of $cref/Scalar/OdeErrControl/Scalar/$$ below). $codei% %tb% %$$ The argument $icode tb$$ has prototype $codei% const %Scalar% &%tb% %$$ It specifies the final time for this step in the ODE integration. $codei% %xa% %$$ The argument $icode xa$$ has prototype $codei% const %Vector% &%xa% %$$ and size $icode n$$. It specifies the value of $latex X(ta)$$. (see description of $cref/Vector/OdeErrControl/Vector/$$ below). $codei% %xb% %$$ The argument value $icode xb$$ has prototype $codei% %Vector% &%xb% %$$ and size $icode n$$. The input value of its elements does not matter. On output, it contains the approximation for $latex X(tb)$$ that the method obtains. $codei% %eb% %$$ The argument value $icode eb$$ has prototype $codei% %Vector% &%eb% %$$ and size $icode n$$. The input value of its elements does not matter. On output, it contains an estimate for the error in the approximation $icode xb$$. It is assumed (locally) that the error bound in this approximation nearly equal to $latex K (tb - ta)^m$$ where $icode K$$ is a fixed constant and $icode m$$ is the corresponding argument to $code CodeControl$$. $subhead Nan$$ If any element of the vector $icode eb$$ or $icode xb$$ are not a number $code nan$$, the current step is considered to large. If this happens with the current step size equal to $icode smin$$, $code OdeErrControl$$ returns with $icode xf$$ and $icode ef$$ as vectors of $code nan$$. $subhead order$$ If $icode m$$ is $code size_t$$, the object $icode method$$ must also support the following syntax $codei% %m% = %method%.order() %$$ The return value $icode m$$ is the order of the error estimate; i.e., there is a constant K such that if $latex ti \leq ta \leq tb \leq tf$$, $latex \[ | eb(tb) | \leq K | tb - ta |^m \] $$ where $icode ta$$, $icode tb$$, and $icode eb$$ are as in $icode%method%.step(%ta%, %tb%, %xa%, %xb%, %eb%)%$$ $head ti$$ The argument $icode ti$$ has prototype $codei% const %Scalar% &%ti% %$$ It specifies the initial time for the integration of the differential equation. $head tf$$ The argument $icode tf$$ has prototype $codei% const %Scalar% &%tf% %$$ It specifies the final time for the integration of the differential equation. $head xi$$ The argument $icode xi$$ has prototype $codei% const %Vector% &%xi% %$$ and size $icode n$$. It specifies value of $latex X(ti)$$. $head smin$$ The argument $icode smin$$ has prototype $codei% const %Scalar% &%smin% %$$ The step size during a call to $icode method$$ is defined as the corresponding value of $latex tb - ta$$. If $latex tf - ti \leq smin$$, the integration will be done in one step of size $icode tf - ti$$. Otherwise, the minimum value of $icode tb - ta$$ will be $latex smin$$ except for the last two calls to $icode method$$ where it may be as small as $latex smin / 2$$. $head smax$$ The argument $icode smax$$ has prototype $codei% const %Scalar% &%smax% %$$ It specifies the maximum step size to use during the integration; i.e., the maximum value for $latex tb - ta$$ in a call to $icode method$$. The value of $icode smax$$ must be greater than or equal $icode smin$$. $head scur$$ The argument $icode scur$$ has prototype $codei% %Scalar% &%scur% %$$ The value of $icode scur$$ is the suggested next step size, based on error criteria, to try in the next call to $icode method$$. On input it corresponds to the first call to $icode method$$, in this call to $code OdeErrControl$$ (where $latex ta = ti$$). On output it corresponds to the next call to $icode method$$, in a subsequent call to $code OdeErrControl$$ (where $icode ta = tf$$). $head eabs$$ The argument $icode eabs$$ has prototype $codei% const %Vector% &%eabs% %$$ and size $icode n$$. Each of the elements of $icode eabs$$ must be greater than or equal zero. It specifies a bound for the absolute error in the return value $icode xf$$ as an approximation for $latex X(tf)$$. (see the $cref/error criteria discussion/OdeErrControl/Error Criteria Discussion/$$ below). $head erel$$ The argument $icode erel$$ has prototype $codei% const %Scalar% &%erel% %$$ and is greater than or equal zero. It specifies a bound for the relative error in the return value $icode xf$$ as an approximation for $latex X(tf)$$ (see the $cref/error criteria discussion/OdeErrControl/Error Criteria Discussion/$$ below). $head ef$$ The argument value $icode ef$$ has prototype $codei% %Vector% &%ef% %$$ and size $icode n$$. The input value of its elements does not matter. On output, it contains an estimated bound for the absolute error in the approximation $icode xf$$; i.e., $latex \[ ef_i > | X( tf )_i - xf_i | \] $$ If on output $icode ef$$ contains not a number $code nan$$, see the discussion of $cref/step/OdeErrControl/Method/Nan/$$. $head maxabs$$ The argument $icode maxabs$$ is optional in the call to $code OdeErrControl$$. If it is present, it has the prototype $codei% %Vector% &%maxabs% %$$ and size $icode n$$. The input value of its elements does not matter. On output, it contains an estimate for the maximum absolute value of $latex X(t)$$; i.e., $latex \[ maxabs[i] \approx \max \left\{ | X( t )_i | \; : \; t \in [ti, tf] \right\} \] $$ $head nstep$$ The argument $icode nstep$$ is optional in the call to $code OdeErrControl$$. If it is present, it has the prototype $codei% %size_t% &%nstep% %$$ Its input value does not matter and its output value is the number of calls to $icode%method%.step%$$ used by $code OdeErrControl$$. $head Error Criteria Discussion$$ The relative error criteria $icode erel$$ and absolute error criteria $icode eabs$$ are enforced during each step of the integration of the ordinary differential equations. In addition, they are inversely scaled by the step size so that the total error bound is less than the sum of the error bounds. To be specific, if $latex \tilde{X} (t)$$ is the approximate solution at time $latex t$$, $icode ta$$ is the initial step time, and $icode tb$$ is the final step time, $latex \[ \left| \tilde{X} (tb)_j - X (tb)_j \right| \leq \frac{tf - ti}{tb - ta} \left[ eabs[j] + erel \; | \tilde{X} (tb)_j | \right] \] $$ If $latex X(tb)_j$$ is near zero for some $latex tb \in [ti , tf]$$, and one uses an absolute error criteria $latex eabs[j]$$ of zero, the error criteria above will force $code OdeErrControl$$ to use step sizes equal to $cref/smin/OdeErrControl/smin/$$ for steps ending near $latex tb$$. In this case, the error relative to $icode maxabs$$ can be judged after $code OdeErrControl$$ returns. If $icode ef$$ is to large relative to $icode maxabs$$, $code OdeErrControl$$ can be called again with a smaller value of $icode smin$$. $head Scalar$$ The type $icode Scalar$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, the following operations must be defined for $icode Scalar$$ objects $icode a$$ and $icode b$$: $table $bold Operation$$ $cnext $bold Description$$ $rnext $icode%a% <= %b%$$ $cnext returns true (false) if $icode a$$ is less than or equal (greater than) $icode b$$. $rnext $icode%a% == %b%$$ $cnext returns true (false) if $icode a$$ is equal to $icode b$$. $rnext $codei%log(%a%)%$$ $cnext returns a $icode Scalar$$ equal to the logarithm of $icode a$$ $rnext $codei%exp(%a%)%$$ $cnext returns a $icode Scalar$$ equal to the exponential of $icode a$$ $tend $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type Scalar/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Example$$ $children% example/ode_err_control.cpp% example/ode_err_maxabs.cpp %$$ The files $cref ode_err_control.cpp$$ and $cref ode_err_maxabs.cpp$$ contain examples and tests of using this routine. They return true if they succeed and false otherwise. $head Theory$$ Let $latex e(s)$$ be the error as a function of the step size $latex s$$ and suppose that there is a constant $latex K$$ such that $latex e(s) = K s^m$$. Let $latex a$$ be our error bound. Given the value of $latex e(s)$$, a step of size $latex \lambda s$$ would be ok provided that $latex \[ \begin{array}{rcl} a & \geq & e( \lambda s ) (tf - ti) / ( \lambda s ) \\ a & \geq & K \lambda^m s^m (tf - ti) / ( \lambda s ) \\ a & \geq & \lambda^{m-1} s^{m-1} (tf - ti) e(s) / s^m \\ a & \geq & \lambda^{m-1} (tf - ti) e(s) / s \\ \lambda^{m-1} & \leq & \frac{a}{e(s)} \frac{s}{tf - ti} \end{array} \] $$ Thus if the right hand side of the last inequality is greater than or equal to one, the step of size $latex s$$ is ok. $head Source Code$$ The source code for this routine is in the file $code cppad/ode_err_control.hpp$$. $end -------------------------------------------------------------------------- */ // link exp and log for float and double # include # include # include # include namespace CppAD { // Begin CppAD namespace template Vector OdeErrControl( Method &method, const Scalar &ti , const Scalar &tf , const Vector &xi , const Scalar &smin , const Scalar &smax , Scalar &scur , const Vector &eabs , const Scalar &erel , Vector &ef , Vector &maxabs, size_t &nstep ) { // check simple vector class specifications CheckSimpleVector(); size_t n = size_t(xi.size()); CPPAD_ASSERT_KNOWN( smin <= smax, "Error in OdeErrControl: smin > smax" ); CPPAD_ASSERT_KNOWN( size_t(eabs.size()) == n, "Error in OdeErrControl: size of eabs is not equal to n" ); CPPAD_ASSERT_KNOWN( size_t(maxabs.size()) == n, "Error in OdeErrControl: size of maxabs is not equal to n" ); size_t m = method.order(); CPPAD_ASSERT_KNOWN( m > 1, "Error in OdeErrControl: m is less than or equal one" ); bool ok; bool minimum_step; size_t i; Vector xa(n), xb(n), eb(n), nan_vec(n); // initialization Scalar zero(0); Scalar one(1); Scalar two(2); Scalar three(3); Scalar m1(m-1); Scalar ta = ti; for(i = 0; i < n; i++) { nan_vec[i] = nan(zero); ef[i] = zero; xa[i] = xi[i]; if( zero <= xi[i] ) maxabs[i] = xi[i]; else maxabs[i] = - xi[i]; } nstep = 0; Scalar tb, step, lambda, axbi, a, r, root; while( ! (ta == tf) ) { // start with value suggested by error criteria step = scur; // check maximum if( smax <= step ) step = smax; // check minimum minimum_step = step <= smin; if( minimum_step ) step = smin; // check if near the end if( tf <= ta + step * three / two ) tb = tf; else tb = ta + step; // try using this step size nstep++; method.step(ta, tb, xa, xb, eb); step = tb - ta; // check if this steps error estimate is ok ok = ! (hasnan(xb) || hasnan(eb)); if( (! ok) && minimum_step ) { ef = nan_vec; return nan_vec; } // compute value of lambda for this step lambda = Scalar(10) * scur / step; for(i = 0; i < n; i++) { if( zero <= xb[i] ) axbi = xb[i]; else axbi = - xb[i]; a = eabs[i] + erel * axbi; if( ! (eb[i] == zero) ) { r = ( a / eb[i] ) * step / (tf - ti); root = exp( log(r) / m1 ); if( root <= lambda ) lambda = root; } } if( ok && ( one <= lambda || step <= smin * three / two) ) { // this step is within error limits or // close to the minimum size ta = tb; for(i = 0; i < n; i++) { xa[i] = xb[i]; ef[i] = ef[i] + eb[i]; if( zero <= xb[i] ) axbi = xb[i]; else axbi = - xb[i]; if( axbi > maxabs[i] ) maxabs[i] = axbi; } } if( ! ok ) { // decrease step an see if method will work this time scur = step / two; } else if( ! (ta == tf) ) { // step suggested by the error criteria is not used // on the last step because it may be very small. scur = lambda * step / two; } } return xa; } template Vector OdeErrControl( Method &method, const Scalar &ti , const Scalar &tf , const Vector &xi , const Scalar &smin , const Scalar &smax , Scalar &scur , const Vector &eabs , const Scalar &erel , Vector &ef ) { Vector maxabs(xi.size()); size_t nstep; return OdeErrControl( method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep ); } template Vector OdeErrControl( Method &method, const Scalar &ti , const Scalar &tf , const Vector &xi , const Scalar &smin , const Scalar &smax , Scalar &scur , const Vector &eabs , const Scalar &erel , Vector &ef , Vector &maxabs) { size_t nstep; return OdeErrControl( method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep ); } } // End CppAD namespace # endif TMB/inst/include/cppad/CMakeLists.txt0000644000176200001440000002041514113627761017135 0ustar liggesusers# $Id:$ # ----------------------------------------------------------------------------- # CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell # # CppAD is distributed under multiple licenses. This distribution is under # the terms of the # GNU General Public License Version 3. # # A copy of this license is included in the COPYING file of this distribution. # Please visit http://www.coin-or.org/CppAD/ for information on other licenses. # ----------------------------------------------------------------------------- # Build the cppad/configure.hpp file. # Inherit environment from ../CMakeLists.txt # ----------------------------------------------------------------------------- MACRO(check_match match_variable match_constant output_variable) STRING(COMPARE EQUAL ${${match_variable}} ${match_constant} match_flag ) IF( match_flag ) SET(${output_variable} 1) ELSE( match_flag ) SET(${output_variable} 0) ENDIF( match_flag ) MESSAGE(STATUS "${output_variable} = ${${output_variable}}" ) ENDMACRO(check_match) # ----------------------------------------------------------------------------- # command line arguments # # cppad_testvector command_line_arg(cppad_testvector cppad STRING "Namespace of vector used for testing, one of: boost, cppad, eigen, std" ) # # cppad_max_num_threads command_line_arg(cppad_max_num_threads 48 STRING "maximum number of threads that CppAD can use use" ) # cppad_sparse_list command_line_arg(cppad_sparse_list YES BOOL "use sparse list for internal sparse set representation" ) # # cppad_tape_id_type command_line_arg(cppad_tape_id_type "unsigned int" STRING "type used to identify different tapes, size must be <= sizeof(size_t)" ) # # cppad_tape_addr_type command_line_arg(cppad_tape_addr_type "unsigned int" STRING "type used to identify variables on one tape, size must be <= sizeof(size_t)" ) # # cppad_implicit_ctor_from_any_type command_line_arg(cppad_implicit_ctor_from_any_type NO BOOL "implicit (instead of explicit) conversion from any type to AD" ) # ----------------------------------------------------------------------------- # cppad_explicit_ctor IF( cppad_implicit_ctor_from_any_type ) SET(cppad_implicit_ctor_from_any_type 1) ELSE( cppad_implicit_ctor_from_any_type ) SET(cppad_implicit_ctor_from_any_type 0) ENDIF( cppad_implicit_ctor_from_any_type ) # ----------------------------------------------------------------------------- # cppad_internal_sparse_set # IF( cppad_sparse_list ) SET(cppad_internal_sparse_set sparse_list ) ELSE( cppad_sparse_list ) SET(cppad_internal_sparse_set sparse_set ) ENDIF( cppad_sparse_list ) MESSAGE(STATUS "cppad_internal_sparse_set = ${cppad_internal_sparse_set}" ) # # ----------------------------------------------------------------------------- # cppad_boostvector, cppad_cppadvector, cppad_eigenvector, cppad_stdvector # check_match(cppad_testvector boost cppad_boostvector) check_match(cppad_testvector cppad cppad_cppadvector) check_match(cppad_testvector eigen cppad_eigenvector) check_match(cppad_testvector std cppad_stdvector) IF( NOT cppad_boostvector ) IF( NOT cppad_cppadvector ) IF( NOT cppad_eigenvector ) IF( NOT cppad_stdvector ) MESSAGE(FATAL_ERROR "cppad_testvector not one of following: boost, cppad, eigen, std." ) ENDIF( NOT cppad_stdvector ) ENDIF( NOT cppad_eigenvector ) ENDIF( NOT cppad_cppadvector ) ENDIF( NOT cppad_boostvector ) IF( cppad_boostvector ) # FIND_PACKAGE(Boost) done by ../CMakeLists.txt IF( NOT Boost_FOUND ) MESSAGE(FATAL_ERROR "cppad_testvector == boost but cannot find boost include files" ) ENDIF( NOT Boost_FOUND ) ENDIF( cppad_boostvector ) # IF( cppad_eigenvector ) IF( NOT eigen_prefix ) MESSAGE(FATAL_ERROR "cppad_testvector == eigen but eigen_prefix is not specified" ) ENDIF( NOT eigen_prefix ) ENDIF( cppad_eigenvector ) # ============================================================================= # Begin C++11 features # ----------------------------------------------------------------------------- # cppad_has_rvalue # SET(source " int main(void) { int&& value = 1 + 2; if( value != 3 ) return 1; return 0; }" ) check_source_runs("${source}" cppad_has_rvalue) # ----------------------------------------------------------------------------- # cppad_has_nullptr # SET(source " int main(void) { char *c = nullptr; return 0; }" ) check_source_runs("${source}" cppad_has_nullptr) # ----------------------------------------------------------------------------- # cppad_has_cstdint_8_to_64 # SET(source " # include template inline bool is_pod(void) { return false; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } int main(void) { return 0; } " ) check_source_runs("${source}" cppad_has_cstdint_8_to_64) # ----------------------------------------------------------------------------- # cppad_compiler_has_erf # SET(source " # include int main(void) { if( std::erf(0.0) == 0.0 ) return 0; return 1; } " ) check_source_runs("${source}" cppad_compiler_has_erf) # ----------------------------------------------------------------------------- # cppad_has_high_resolution_clock # SET(source " # include int main(void) { std::chrono::time_point start, end; start = std::chrono::high_resolution_clock::now(); end = std::chrono::high_resolution_clock::now(); std::chrono::duration difference = end - start; double elapsed_seconds = difference.count(); if( elapsed_seconds > 0.0 ) return 0; return 1; } " ) check_source_runs("${source}" cppad_has_high_resolution_clock) # ============================================================================= # End C++11 features # ----------------------------------------------------------------------------- # cppad_has_gettimeofday # SET(source " # include int main(void) { struct timeval time; gettimeofday(&time, 0); return 0; }" ) check_source_runs("${source}" cppad_has_gettimeofday) # ----------------------------------------------------------------------------- # cppad_size_t_not_unsigned_int # SET(source " # include template inline bool is_pod(void) { return false; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } int main(void) { return 0; } " ) check_source_runs("${source}" cppad_size_t_not_unsigned_int) # ----------------------------------------------------------------------------- # cppad_tape_addr_type, cppad_tape_id_type # FOREACH(cmake_var cppad_tape_id_type cppad_tape_addr_type ) SET(source " # include int main(void) { bool is_unsigned = ! std::numeric_limits<${${cmake_var}}>::is_signed; return int(! is_unsigned); } " ) check_source_runs("${source}" ${cmake_var}_is_unsigned) IF( ${cmake_var}_is_unsigned STREQUAL 0 ) MESSAGE(STATUS "Warning: using a signed ${cmake_var} is for CppAD developers only !" ) ENDIF( ${cmake_var}_is_unsigned STREQUAL 0 ) ENDFOREACH( cmake_var ) # ----------------------------------------------------------------------------- # cppad_max_num_threads # SET(CMAKE_REQUIRED_INCLUDES "") SET(CMAKE_REQUIRED_LIBRARIES "") SET(CMAKE_REQUIRED_FLAGS ) SET(source " int main(void) { const char* number = \"${cppad_max_num_threads}\"; int value = 0; while( *number == ' ' ) number++; while( '0' <= *number && *number <= '9' ) { value = 10 * value + (int)(*number - '0'); number++; } while( *number == ' ' ) number++; if( *number != char(0) ) return 1; if( value < 4 ) return 1; return 0; } " ) CHECK_CXX_SOURCE_RUNS("${source}" cppad_max_num_threads_is_integer_ge_4) IF( NOT cppad_max_num_threads_is_integer_ge_4 ) MESSAGE(FATAL_ERROR "cppad_max_num_threads is not an integer greater than or equal 4" ) ENDIF( NOT cppad_max_num_threads_is_integer_ge_4 ) # ----------------------------------------------------------------------------- # Copy a file to another location and modify its contents. # configure_file(InputFile OutputFile [COPYONLY] [ESCAPE_QUOTES] [@ONLY]) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/configure.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/configure.hpp ) TMB/inst/include/cppad/Rosen34.h0000644000176200001440000000005214113627761015776 0ustar liggesusers/* $Id$ */ # include "cppad/rosen_34.hpp" TMB/inst/include/cppad/omp_alloc.hpp0000644000176200001440000005007514536067013017055 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_OMP_ALLOC_INCLUDED # define CPPAD_OMP_ALLOC_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # ifdef _OPENMP # include # endif namespace CppAD { // BEGIN_CPPAD_NAMESPACE class omp_alloc{ // ============================================================================ public: /* $begin omp_max_num_threads$$ $spell inv CppAD num omp_alloc $$ $section Set and Get Maximum Number of Threads for omp_alloc Allocator$$ $head Deprecated$$ $index set_max_num_threads, omp_alloc$$ $index get_max_num_threads, omp_alloc$$ Use the functions $cref/thread_alloc::parallel_setup/ta_parallel_setup/$$ and $cref/thread_alloc:num_threads/ta_num_threads/$$ instead. $head Syntax$$ $codei%omp_alloc::set_max_num_threads(%number%) %$$ $icode%number% = omp_alloc::get_max_num_threads() %$$ $head Purpose$$ By default there is only one thread and all execution is in sequential mode (not $cref/parallel/omp_in_parallel/$$). $head number$$ The argument and return value $icode number$$ has prototype $codei% size_t %number% %$$ and must be greater than zero. $head set_max_num_threads$$ Informs $cref omp_alloc$$ of the maximum number of OpenMP threads. $head get_max_num_threads$$ Returns the valued used in the previous call to $code set_max_num_threads$$. If there was no such previous call, the value one is returned (and only thread number zero can use $cref omp_alloc$$). $head Restrictions$$ The function $code set_max_num_threads$$ must be called before the program enters $cref/parallel/omp_in_parallel/$$ execution mode. In addition, this function cannot be called while in parallel mode. $end */ /*! Inform omp_alloc of the maximum number of OpenMP threads and enable parallel execution mode by initializing all statics in this file. \param number [in] maximum number of OpenMP threads. */ static void set_max_num_threads(size_t number) { thread_alloc::parallel_setup( number, omp_alloc::in_parallel, omp_alloc::get_thread_num ); thread_alloc::hold_memory(number > 1); } /*! Get the current maximum number of OpenMP threads that omp_alloc can use. \return maximum number of OpenMP threads. */ static size_t get_max_num_threads(void) { return thread_alloc::num_threads(); } /* ----------------------------------------------------------------------- $begin omp_in_parallel$$ $section Is The Current Execution in OpenMP Parallel Mode$$ $spell omp_alloc bool $$ $head Deprecated$$ $index in_parallel, omp_alloc$$ $index omp_alloc, in_parallel$$ Use the function $cref/thread_alloc::in_parallel/ta_in_parallel/$$ instead. $head Syntax$$ $icode%flag% = omp_alloc::in_parallel()%$$ $head Purpose$$ Some of the $cref omp_alloc$$ allocation routines have different specifications for parallel (not sequential) execution mode. This routine enables you to determine if the current execution mode is sequential or parallel. $head flag$$ The return value has prototype $codei% bool %flag% %$$ It is true if the current execution is in parallel mode (possibly multi-threaded) and false otherwise (sequential mode). $head Example$$ $cref omp_alloc.cpp$$ $end */ /// Are we in a parallel execution state; i.e., is it possible that /// other threads are currently executing. static bool in_parallel(void) { # ifdef _OPENMP return static_cast( omp_in_parallel() ); # else return false; # endif } /* ----------------------------------------------------------------------- $begin omp_get_thread_num$$ $spell CppAD num omp_alloc cppad.hpp $$ $section Get the Current OpenMP Thread Number$$ $head Deprecated$$ $index get_thread_num, omp_alloc$$ $index omp_alloc, get_thread_num$$ Use the function $cref/thread_alloc::thread_num/ta_thread_num/$$ instead. $head Syntax$$ $icode%thread% = omp_alloc::get_thread_num()%$$ $head Purpose$$ Some of the $cref omp_alloc$$ allocation routines have a thread number. This routine enables you to determine the current thread. $head thread$$ The return value $icode thread$$ has prototype $codei% size_t %thread% %$$ and is the currently executing thread number. If $code _OPENMP$$ is not defined, $icode thread$$ is zero. $head Example$$ $cref omp_alloc.cpp$$ $end */ /// Get current OpenMP thread number (zero if _OpenMP not defined). static size_t get_thread_num(void) { # ifdef _OPENMP size_t thread = static_cast( omp_get_thread_num() ); return thread; # else return 0; # endif } /* ----------------------------------------------------------------------- $begin omp_get_memory$$ $spell num ptr omp_alloc $$ $section Get At Least A Specified Amount of Memory$$ $head Deprecated$$ $index get_thread_num, omp_alloc$$ $index omp_alloc, get_thread_num$$ Use the function $cref/thread_alloc::get_memory/ta_get_memory/$$ instead. $head Syntax$$ $icode%v_ptr% = omp_alloc::get_memory(%min_bytes%, %cap_bytes%)%$$ $head Purpose$$ Use $cref omp_alloc$$ to obtain a minimum number of bytes of memory (for use by the $cref/current thread/omp_get_thread_num/$$). $head min_bytes$$ This argument has prototype $codei% size_t %min_bytes% %$$ It specifies the minimum number of bytes to allocate. $head cap_bytes$$ This argument has prototype $codei% size_t& %cap_bytes% %$$ It's input value does not matter. Upon return, it is the actual number of bytes (capacity) that have been allocated for use, $codei% %min_bytes% <= %cap_bytes% %$$ $head v_ptr$$ The return value $icode v_ptr$$ has prototype $codei% void* %v_ptr% %$$ It is the location where the $icode cap_bytes$$ of memory that have been allocated for use begins. $head Allocation Speed$$ This allocation should be faster if the following conditions hold: $list number$$ The memory allocated by a previous call to $code get_memory$$ is currently available for use. $lnext The current $icode min_bytes$$ is between the previous $icode min_bytes$$ and previous $icode cap_bytes$$. $lend $head Example$$ $cref omp_alloc.cpp$$ $end */ /*! Use omp_alloc to get a specified amount of memory. If the memory allocated by a previous call to \c get_memory is now avaialable, and \c min_bytes is between its previous value and the previous \c cap_bytes, this memory allocation will have optimal speed. Otherwise, the memory allocation is more complicated and may have to wait for other threads to complete an allocation. \param min_bytes [in] The minimum number of bytes of memory to be obtained for use. \param cap_bytes [out] The actual number of bytes of memory obtained for use. \return pointer to the beginning of the memory allocted for use. */ static void* get_memory(size_t min_bytes, size_t& cap_bytes) { return thread_alloc::get_memory(min_bytes, cap_bytes); } /* ----------------------------------------------------------------------- $begin omp_return_memory$$ $spell ptr omp_alloc $$ $section Return Memory to omp_alloc$$ $head Deprecated$$ $index return_memory, omp_alloc$$ $index omp_alloc, return_memory$$ Use the function $cref/thread_alloc::return_memory/ta_return_memory/$$ instead. $head Syntax$$ $codei%omp_alloc::return_memory(%v_ptr%)%$$ $head Purpose$$ If $cref omp_max_num_threads$$ is one, the memory is returned to the system. Otherwise, the memory is retained by $cref omp_alloc$$ for quick future use by the thread that allocated to memory. $head v_ptr$$ This argument has prototype $codei% void* %v_ptr% %$$. It must be a pointer to memory that is currently in use; i.e. obtained by a previous call to $cref omp_get_memory$$ and not yet returned. $head Thread$$ Either the $cref/current thread/omp_get_thread_num/$$ must be the same as during the corresponding call to $cref omp_get_memory$$, or the current execution mode must be sequential (not $cref/parallel/omp_in_parallel/$$). $head NDEBUG$$ If $code NDEBUG$$ is defined, $icode v_ptr$$ is not checked (this is faster). Otherwise, a list of in use pointers is searched to make sure that $icode v_ptr$$ is in the list. $head Example$$ $cref omp_alloc.cpp$$ $end */ /*! Return memory that was obtained by \c get_memory. If max_num_threads(0) == 1, the memory is returned to the system. Otherwise, it is retained by \c omp_alloc and available for use by \c get_memory for this thread. \param v_ptr [in] Value of the pointer returned by \c get_memory and still in use. After this call, this pointer will available (and not in use). \par We must either be in sequential (not parallel) execution mode, or the current thread must be the same as for the corresponding call to \c get_memory. */ static void return_memory(void* v_ptr) { thread_alloc::return_memory(v_ptr); } /* ----------------------------------------------------------------------- $begin omp_free_available$$ $spell omp_alloc $$ $section Free Memory Currently Available for Quick Use by a Thread$$ $head Deprecated$$ $index free_available, omp_alloc$$ $index omp_alloc, free_available$$ Use the function $cref/thread_alloc::free_available/ta_free_available/$$ instead. $head Syntax$$ $codei%omp_alloc::free_available(%thread%)%$$ $head Purpose$$ Free memory, currently available for quick use by a specific thread, for general future use. $head thread$$ This argument has prototype $codei% size_t %thread% %$$ Either $cref omp_get_thread_num$$ must be the same as $icode thread$$, or the current execution mode must be sequential (not $cref/parallel/omp_in_parallel/$$). $head Example$$ $cref omp_alloc.cpp$$ $end */ /*! Return all the memory being held as available for a thread to the system. \param thread [in] this thread that will no longer have any available memory after this call. This must either be the thread currently executing, or we must be in sequential (not parallel) execution mode. */ static void free_available(size_t thread) { thread_alloc::free_available(thread); } /* ----------------------------------------------------------------------- $begin omp_inuse$$ $spell num inuse omp_alloc $$ $section Amount of Memory a Thread is Currently Using$$ $head Deprecated$$ $index inuse, omp_alloc$$ $index omp_alloc, inuse$$ $head Syntax$$ $icode%num_bytes% = omp_alloc::inuse(%thread%)%$$ Use the function $cref/thread_alloc::inuse/ta_inuse/$$ instead. $head Purpose$$ Memory being managed by $cref omp_alloc$$ has two states, currently in use by the specified thread, and quickly available for future use by the specified thread. This function informs the program how much memory is in use. $head thread$$ This argument has prototype $codei% size_t %thread% %$$ Either $cref omp_get_thread_num$$ must be the same as $icode thread$$, or the current execution mode must be sequential (not $cref/parallel/omp_in_parallel/$$). $head num_bytes$$ The return value has prototype $codei% size_t %num_bytes% %$$ It is the number of bytes currently in use by the specified thread. $head Example$$ $cref omp_alloc.cpp$$ $end */ /*! Determine the amount of memory that is currently inuse. \param thread [in] Thread for which we are determining the amount of memory (must be < CPPAD_MAX_NUM_THREADS). Durring parallel execution, this must be the thread that is currently executing. \return The amount of memory in bytes. */ static size_t inuse(size_t thread) { return thread_alloc::inuse(thread); } /* ----------------------------------------------------------------------- $begin omp_available$$ $spell num omp_alloc $$ $section Amount of Memory Available for Quick Use by a Thread$$ $head Deprecated$$ $index available, omp_alloc$$ $index omp_alloc, available$$ Use the function $cref/thread_alloc::available/ta_available/$$ instead. $head Syntax$$ $icode%num_bytes% = omp_alloc::available(%thread%)%$$ $head Purpose$$ Memory being managed by $cref omp_alloc$$ has two states, currently in use by the specified thread, and quickly available for future use by the specified thread. This function informs the program how much memory is available. $head thread$$ This argument has prototype $codei% size_t %thread% %$$ Either $cref omp_get_thread_num$$ must be the same as $icode thread$$, or the current execution mode must be sequential (not $cref/parallel/omp_in_parallel/$$). $head num_bytes$$ The return value has prototype $codei% size_t %num_bytes% %$$ It is the number of bytes currently available for use by the specified thread. $head Example$$ $cref omp_alloc.cpp$$ $end */ /*! Determine the amount of memory that is currently available for use. \copydetails inuse */ static size_t available(size_t thread) { return thread_alloc::available(thread); } /* ----------------------------------------------------------------------- $begin omp_create_array$$ $spell omp_alloc sizeof $$ $section Allocate Memory and Create A Raw Array$$ $head Deprecated$$ $index create_array, omp_alloc$$ $index omp_alloc, create_array$$ Use the function $cref/thread_alloc::create_array/ta_create_array/$$ instead. $head Syntax$$ $icode%array% = omp_alloc::create_array<%Type%>(%size_min%, %size_out%)%$$. $head Purpose$$ Create a new raw array using $cref omp_alloc$$ a fast memory allocator that works well in a multi-threading OpenMP environment. $head Type$$ The type of the elements of the array. $head size_min$$ This argument has prototype $codei% size_t %size_min% %$$ This is the minimum number of elements that there can be in the resulting $icode array$$. $head size_out$$ This argument has prototype $codei% size_t& %size_out% %$$ The input value of this argument does not matter. Upon return, it is the actual number of elements in $icode array$$ ($icode% size_min %<=% size_out%$$). $head array$$ The return value $icode array$$ has prototype $codei% %Type%* %array% %$$ It is array with $icode size_out$$ elements. The default constructor for $icode Type$$ is used to initialize the elements of $icode array$$. Note that $cref omp_delete_array$$ should be used to destroy the array when it is no longer needed. $head Delta$$ The amount of memory $cref omp_inuse$$ by the current thread, will increase $icode delta$$ where $codei% sizeof(%Type%) * (%size_out% + 1) > %delta% >= sizeof(%Type%) * %size_out% %$$ The $cref omp_available$$ memory will decrease by $icode delta$$, (and the allocation will be faster) if a previous allocation with $icode size_min$$ between its current value and $icode size_out$$ is available. $head Example$$ $cref omp_alloc.cpp$$ $end */ /*! Use omp_alloc to Create a Raw Array. \tparam Type The type of the elements of the array. \param size_min [in] The minimum number of elements in the array. \param size_out [out] The actual number of elements in the array. \return pointer to the first element of the array. The default constructor is used to initialize all the elements of the array. \par The \c extra_ field, in the \c omp_alloc node before the return value, is set to size_out. */ template static Type* create_array(size_t size_min, size_t& size_out) { return thread_alloc::create_array(size_min, size_out); } /* ----------------------------------------------------------------------- $begin omp_delete_array$$ $spell omp_alloc sizeof $$ $section Return A Raw Array to The Available Memory for a Thread$$ $head Deprecated$$ $index delete_array, omp_alloc$$ $index omp_alloc, delete_array$$ Use the function $cref/thread_alloc::delete_array/ta_delete_array/$$ instead. $head Syntax$$ $codei%omp_alloc::delete_array(%array%)%$$. $head Purpose$$ Returns memory corresponding to a raw array (create by $cref omp_create_array$$) to the $cref omp_available$$ memory pool for the current thread. $head Type$$ The type of the elements of the array. $head array$$ The argument $icode array$$ has prototype $codei% %Type%* %array% %$$ It is a value returned by $cref omp_create_array$$ and not yet deleted. The $icode Type$$ destructor is called for each element in the array. $head Thread$$ The $cref/current thread/omp_get_thread_num/$$ must be the same as when $cref omp_create_array$$ returned the value $icode array$$. There is an exception to this rule: when the current execution mode is sequential (not $cref/parallel/omp_in_parallel/$$) the current thread number does not matter. $head Delta$$ The amount of memory $cref omp_inuse$$ will decrease by $icode delta$$, and the $cref omp_available$$ memory will increase by $icode delta$$, where $cref/delta/omp_create_array/Delta/$$ is the same as for the corresponding call to $code create_array$$. $head Example$$ $cref omp_alloc.cpp$$ $end */ /*! Return Memory Used for a Raw Array to the Available Pool. \tparam Type The type of the elements of the array. \param array [in] A value returned by \c create_array that has not yet been deleted. The \c Type destructor is used to destroy each of the elements of the array. \par Durring parallel execution, the current thread must be the same as during the corresponding call to \c create_array. */ template static void delete_array(Type* array) { thread_alloc::delete_array(array); } }; /* -------------------------------------------------------------------------- $begin omp_efficient$$ $spell omp_alloc ptr num bool const $$ $section Check If A Memory Allocation is Efficient for Another Use$$ $head Removed$$ $index efficient, omp_alloc$$ $index omp_alloc, efficient$$ This function has been removed because speed tests seem to indicate it is just as fast, or faster, to free and then reallocate the memory. $head Syntax$$ $icode%flag% = omp_alloc::efficient(%v_ptr%, %num_bytes%)%$$ $head Purpose$$ Check if memory that is currently in use is an efficient allocation for a specified number of bytes. $head v_ptr$$ This argument has prototype $codei% const void* %v_ptr% %$$. It must be a pointer to memory that is currently in use; i.e. obtained by a previous call to $cref omp_get_memory$$ and not yet returned. $head num_bytes$$ This argument has prototype $codei% size_t %num_bytes% %$$ It specifies the number of bytes of the memory allocated by $icode v_ptr$$ that we want to use. $head flag$$ The return value has prototype $codei% bool %flag% %$$ It is true, a call to $code get_memory$$ with $cref/min_bytes/omp_get_memory/min_bytes/$$ equal to $icode num_bytes$$ would result in a value for $cref/cap_bytes/omp_get_memory/cap_bytes/$$ that is the same as when $code v_ptr$$ was returned by $code get_memory$$; i.e., $icode v_ptr$$ is an efficient memory block for $icode num_bytes$$ bytes of information. $head Thread$$ Either the $cref/current thread/omp_get_thread_num/$$ must be the same as during the corresponding call to $cref omp_get_memory$$, or the current execution mode must be sequential (not $cref/parallel/omp_in_parallel/$$). $head NDEBUG$$ If $code NDEBUG$$ is defined, $icode v_ptr$$ is not checked (this is faster). Otherwise, a list of in use pointers is searched to make sure that $icode v_ptr$$ is in the list. $end --------------------------------------------------------------------------- $begin old_max_num_threads$$ $spell inv CppAD num omp_alloc $$ $section Set Maximum Number of Threads for omp_alloc Allocator$$ $head Removed$$ $index max_num_threads, omp_alloc$$ $index omp_alloc, max_num_threads$$ This function has been removed from the CppAD API. Use the function $cref/thread_alloc::parallel_setup/ta_parallel_setup/$$ in its place. $head Syntax$$ $codei%omp_alloc::max_num_threads(%number%)%$$ $head Purpose$$ By default there is only one thread and all execution is in sequential mode (not $cref/parallel/omp_in_parallel/$$). $head number$$ The argument $icode number$$ has prototype $codei% size_t %number% %$$ It must be greater than zero and specifies the maximum number of OpenMP threads that will be active at one time. $head Restrictions$$ This function must be called before the program enters $cref/parallel/omp_in_parallel/$$ execution mode. $end ------------------------------------------------------------------------------- */ } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/ErrorHandler.h0000644000176200001440000000005714113627761017135 0ustar liggesusers/* $Id$ */ # include "cppad/error_handler.hpp" TMB/inst/include/cppad/lu_solve.hpp0000644000176200001440000002336114536067012016735 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_LU_SOLVE_INCLUDED # define CPPAD_LU_SOLVE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin LuSolve$$ $escape #$$ $spell cppad.hpp det exp Leq typename bool const namespace std Geq Lu CppAD signdet logdet $$ $index LuSolve$$ $index linear, equation$$ $index equation, linear$$ $index determinant, Lu$$ $index solve, linear equation$$ $section Compute Determinant and Solve Linear Equations$$ $pre $$ $head Syntax$$ $code# include $$ $pre $$ $icode%signdet% = LuSolve(%n%, %m%, %A%, %B%, %X%, %logdet%)%$$ $head Description$$ Use an LU factorization of the matrix $icode A$$ to compute its determinant and solve for $icode X$$ in the linear of equation $latex \[ A * X = B \] $$ where $icode A$$ is an $icode n$$ by $icode n$$ matrix, $icode X$$ is an $icode n$$ by $icode m$$ matrix, and $icode B$$ is an $latex n x m$$ matrix. $head Include$$ The file $code cppad/lu_solve.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Factor and Invert$$ This routine is an easy to user interface to $cref LuFactor$$ and $cref LuInvert$$ for computing determinants and solutions of linear equations. These separate routines should be used if one right hand side $icode B$$ depends on the solution corresponding to another right hand side (with the same value of $icode A$$). In this case only one call to $code LuFactor$$ is required but there will be multiple calls to $code LuInvert$$. $head Matrix Storage$$ All matrices are stored in row major order. To be specific, if $latex Y$$ is a vector that contains a $latex p$$ by $latex q$$ matrix, the size of $latex Y$$ must be equal to $latex p * q $$ and for $latex i = 0 , \ldots , p-1$$, $latex j = 0 , \ldots , q-1$$, $latex \[ Y_{i,j} = Y[ i * q + j ] \] $$ $head signdet$$ The return value $icode signdet$$ is a $code int$$ value that specifies the sign factor for the determinant of $icode A$$. This determinant of $icode A$$ is zero if and only if $icode signdet$$ is zero. $head n$$ The argument $icode n$$ has type $code size_t$$ and specifies the number of rows in the matrices $icode A$$, $icode X$$, and $icode B$$. The number of columns in $icode A$$ is also equal to $icode n$$. $head m$$ The argument $icode m$$ has type $code size_t$$ and specifies the number of columns in the matrices $icode X$$ and $icode B$$. If $icode m$$ is zero, only the determinant of $icode A$$ is computed and the matrices $icode X$$ and $icode B$$ are not used. $head A$$ The argument $icode A$$ has the prototype $codei% const %FloatVector% &%A% %$$ and the size of $icode A$$ must equal $latex n * n$$ (see description of $cref/FloatVector/LuSolve/FloatVector/$$ below). This is the $latex n$$ by $icode n$$ matrix that we are computing the determinant of and that defines the linear equation. $head B$$ The argument $icode B$$ has the prototype $codei% const %FloatVector% &%B% %$$ and the size of $icode B$$ must equal $latex n * m$$ (see description of $cref/FloatVector/LuSolve/FloatVector/$$ below). This is the $latex n$$ by $icode m$$ matrix that defines the right hand side of the linear equations. If $icode m$$ is zero, $icode B$$ is not used. $head X$$ The argument $icode X$$ has the prototype $codei% %FloatVector% &%X% %$$ and the size of $icode X$$ must equal $latex n * m$$ (see description of $cref/FloatVector/LuSolve/FloatVector/$$ below). The input value of $icode X$$ does not matter. On output, the elements of $icode X$$ contain the solution of the equation we wish to solve (unless $icode signdet$$ is equal to zero). If $icode m$$ is zero, $icode X$$ is not used. $head logdet$$ The argument $icode logdet$$ has prototype $codei% %Float% &%logdet% %$$ On input, the value of $icode logdet$$ does not matter. On output, it has been set to the log of the determinant of $icode A$$ (but not quite). To be more specific, the determinant of $icode A$$ is given by the formula $codei% %det% = %signdet% * exp( %logdet% ) %$$ This enables $code LuSolve$$ to use logs of absolute values in the case where $icode Float$$ corresponds to a real number. $head Float$$ The type $icode Float$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, the following operations must be defined for any pair of $icode Float$$ objects $icode x$$ and $icode y$$: $table $bold Operation$$ $cnext $bold Description$$ $rnext $codei%log(%x%)%$$ $cnext returns the logarithm of $icode x$$ as a $icode Float$$ object $tend $head FloatVector$$ The type $icode FloatVector$$ must be a $cref SimpleVector$$ class with $cref/elements of type Float/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head LeqZero$$ Including the file $code lu_solve.hpp$$ defines the template function $codei% template bool LeqZero<%Float%>(const %Float% &%x%) %$$ in the $code CppAD$$ namespace. This function returns true if $icode x$$ is less than or equal to zero and false otherwise. It is used by $code LuSolve$$ to avoid taking the log of zero (or a negative number if $icode Float$$ corresponds to real numbers). This template function definition assumes that the operator $code <=$$ is defined for $icode Float$$ objects. If this operator is not defined for your use of $icode Float$$, you will need to specialize this template so that it works for your use of $code LuSolve$$. $pre $$ Complex numbers do not have the operation or $code <=$$ defined. In addition, in the complex case, one can take the log of a negative number. The specializations $codei% bool LeqZero< std::complex > (const std::complex &%x%) bool LeqZero< std::complex >(const std::complex &%x%) %$$ are defined by including $code lu_solve.hpp$$. These return true if $icode x$$ is zero and false otherwise. $head AbsGeq$$ Including the file $code lu_solve.hpp$$ defines the template function $codei% template bool AbsGeq<%Float%>(const %Float% &%x%, const %Float% &%y%) %$$ If the type $icode Float$$ does not support the $code <=$$ operation and it is not $code std::complex$$ or $code std::complex$$, see the documentation for $code AbsGeq$$ in $cref/LuFactor/LuFactor/AbsGeq/$$. $children% example/lu_solve.cpp% omh/lu_solve_hpp.omh %$$ $head Example$$ The file $cref lu_solve.cpp$$ contains an example and test of using this routine. It returns true if it succeeds and false otherwise. $head Source$$ The file $cref lu_solve.hpp$$ contains the current source code that implements these specifications. $end -------------------------------------------------------------------------- */ // BEGIN C++ # include # include // link exp for float and double cases # include # include # include # include # include # include namespace CppAD { // BEGIN CppAD namespace // LeqZero template inline bool LeqZero(const Float &x) { return x <= Float(0); } inline bool LeqZero( const std::complex &x ) { return x == std::complex(0); } inline bool LeqZero( const std::complex &x ) { return x == std::complex(0); } // LuSolve template int LuSolve( size_t n , size_t m , const FloatVector &A , const FloatVector &B , FloatVector &X , Float &logdet ) { // check numeric type specifications CheckNumericType(); // check simple vector class specifications CheckSimpleVector(); size_t p; // index of pivot element (diagonal of L) int signdet; // sign of the determinant Float pivot; // pivot element // the value zero const Float zero(0); // pivot row and column order in the matrix std::vector ip(n); std::vector jp(n); // ------------------------------------------------------- CPPAD_ASSERT_KNOWN( size_t(A.size()) == n * n, "Error in LuSolve: A must have size equal to n * n" ); CPPAD_ASSERT_KNOWN( size_t(B.size()) == n * m, "Error in LuSolve: B must have size equal to n * m" ); CPPAD_ASSERT_KNOWN( size_t(X.size()) == n * m, "Error in LuSolve: X must have size equal to n * m" ); // ------------------------------------------------------- // copy A so that it does not change FloatVector Lu(A); // copy B so that it does not change X = B; // Lu factor the matrix A signdet = LuFactor(ip, jp, Lu); // compute the log of the determinant logdet = Float(0); for(p = 0; p < n; p++) { // pivot using the max absolute element pivot = Lu[ ip[p] * n + jp[p] ]; // check for determinant equal to zero if( pivot == zero ) { // abort the mission logdet = Float(0); return 0; } // update the determinant if( LeqZero ( pivot ) ) { logdet += log( - pivot ); signdet = - signdet; } else logdet += log( pivot ); } // solve the linear equations LuInvert(ip, jp, Lu, X); // return the sign factor for the determinant return signdet; } } // END CppAD namespace // END C++ # endif TMB/inst/include/cppad/thread_alloc.hpp0000644000176200001440000013065314536067013017532 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_THREAD_ALLOC_INCLUDED # define CPPAD_THREAD_ALLOC_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include # include # ifdef _MSC_VER // Supress warning that Microsoft compiler changed its behavior and is now // doing the correct thing at the statement: // new(array + i) Type(); # pragma warning(disable:4345) # endif # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file thread_alloc.hpp File used to define the CppAD multi-threading allocaor class */ /*! \def CPPAD_MAX_NUM_CAPACITY Maximum number of different capacities the allocator will attempt. This must be larger than the log base two of numeric_limit::max(). */ # define CPPAD_MAX_NUM_CAPACITY 100 /*! \def CPPAD_MIN_DOUBLE_CAPACITY Minimum number of double values that will fit in an allocation. */ # define CPPAD_MIN_DOUBLE_CAPACITY 16 /*! \def CPPAD_TRACE_CAPACITY If NDEBUG is not defined, print all calls to \c get_memory and \c return_memory that correspond to this capacity and thread CPPAD_TRACE_THREAD. (Note that if CPPAD_TRACE_CAPACITY is zero, or any other value not in the list of capacities, no tracing will be done.) */ # define CPPAD_TRACE_CAPACITY 0 /*! \def CPPAD_TRACE_THREAD If NDEBUG is not defined, print all calls to \c get_memory and \c return_memory that correspond to this thead and capacity CPPAD_TRACE_CAPACITY. */ # define CPPAD_TRACE_THREAD 0 /* Note that Section 3.6.2 of ISO/IEC 14882:1998(E) states: "The storage for objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place." */ /*! Capacity vector for memory allocation block sizes. Only one of these objects should be created and used as a static variable inside of the \c thread_alloc::capacity_info function. */ /*! Allocator class that works well with an multi-threading environment. */ class thread_alloc{ // ============================================================================ private: class capacity_t { public: /// number of capacity values actually used size_t number; /// the different capacity values size_t value[CPPAD_MAX_NUM_CAPACITY]; /// ctor capacity_t(void) { // Cannot figure out how to call thread_alloc::in_parallel here. // CPPAD_ASSERT_UNKNOWN( // ! thread_alloc::in_parallel() , "thread_alloc: " // "parallel mode and parallel_setup not yet called." // ); number = 0; size_t capacity = CPPAD_MIN_DOUBLE_CAPACITY * sizeof(double); while( capacity < std::numeric_limits::max() / 2 ) { CPPAD_ASSERT_UNKNOWN( number < CPPAD_MAX_NUM_CAPACITY ); value[number++] = capacity; // next capactiy is 3/2 times the current one capacity = 3 * ( (capacity + 1) / 2 ); } CPPAD_ASSERT_UNKNOWN( number > 0 ); } }; class block_t { public: /// extra information (currently used by create and delete array) size_t extra_; /// an index that uniquely idenfifies both thread and capacity size_t tc_index_; /// pointer to the next memory allocation with the same tc_index_ void* next_; // ----------------------------------------------------------------- /// make default constructor private. It is only used by constructor /// for `root arrays below. block_t(void) : extra_(0), tc_index_(0), next_(CPPAD_NULL) { } }; // --------------------------------------------------------------------- /// Vector of fixed capacity values for this allocator static const capacity_t* capacity_info(void) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static const capacity_t capacity; return &capacity; } // --------------------------------------------------------------------- /// Structure of information for each thread struct thread_alloc_info { /// count of available bytes for this thread size_t count_inuse_; /// count of inuse bytes for this thread size_t count_available_; /// root of available list for this thread and each capacity block_t root_available_[CPPAD_MAX_NUM_CAPACITY]; /// root of inuse list for this thread and each capacity /// If NDEBUG is true, this memory is not used, but it still /// helps separate this structure from one for the next thread. block_t root_inuse_[CPPAD_MAX_NUM_CAPACITY]; }; // --------------------------------------------------------------------- /*! Set and Get hold available memory flag. \param set [in] if true, the value returned by this return is changed. \param new_value [in] if \a set is true, this is the new value returned by this routine. Otherwise, \c new_value is ignored. \return the current setting for this routine (which is initially false). */ static bool set_get_hold_memory(bool set, bool new_value = false) { static bool value = false; if( set ) value = new_value; return value; } // --------------------------------------------------------------------- /*! Get pointer to the information for this thread. \param thread [in] Is the thread number for this information pointer. \param clear If \a clear is true, then the information pointer for this thread is deleted and the \c CPPAD_NULL pointer is returned. There must be no memory currently in either the inuse or avaialble lists when this routine is called. \return is the current informaiton pointer for this thread. If \a clear is false, and the current pointer is CPPAD_NULL, a new infromation record is allocated and its pointer returned. In this case, if \c info is the retured pointer, info->count_inuse == 0 and info->count_available == 0. In addition, for c = 0 , ... , CPPAD_MAX_NUM_CAPACITY-1 info->root_inuse_[c].next_ == CPPAD_NULL and info->root_available_[c].next_ == CPPAD_NULL. */ static thread_alloc_info* thread_info( size_t thread , bool clear = false ) { static thread_alloc_info* all_info[CPPAD_MAX_NUM_THREADS]; static thread_alloc_info zero_info; CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS ); thread_alloc_info* info = all_info[thread]; if( clear ) { if( info != CPPAD_NULL ) { # ifndef NDEBUG CPPAD_ASSERT_UNKNOWN( info->count_inuse_ == 0 && info->count_available_ == 0 ); for(size_t c = 0; c < CPPAD_MAX_NUM_CAPACITY; c++) { CPPAD_ASSERT_UNKNOWN( info->root_inuse_[c].next_ == CPPAD_NULL && info->root_available_[c].next_ == CPPAD_NULL ); } # endif if( thread != 0 ) ::operator delete( reinterpret_cast(info) ); info = CPPAD_NULL; all_info[thread] = info; } } else if( info == CPPAD_NULL ) { if( thread == 0 ) info = &zero_info; else { size_t size = sizeof(thread_alloc_info); void* v_ptr = ::operator new(size); info = reinterpret_cast(v_ptr); } all_info[thread] = info; // initialize the information record for(size_t c = 0; c < CPPAD_MAX_NUM_CAPACITY; c++) { info->root_inuse_[c].next_ = CPPAD_NULL; info->root_available_[c].next_ = CPPAD_NULL; } info->count_inuse_ = 0; info->count_available_ = 0; } return info; } // ----------------------------------------------------------------------- /*! Increase the number of bytes of memory that are currently in use; i.e., that been obtained with \c get_memory and not yet returned. \param inc [in] amount to increase memory in use. \param thread [in] Thread for which we are increasing the number of bytes in use (must be less than \c num_threads). Durring parallel execution, this must be the thread that is currently executing. */ static void inc_inuse(size_t inc, size_t thread) { CPPAD_ASSERT_UNKNOWN( thread < num_threads() ); CPPAD_ASSERT_UNKNOWN( thread == thread_num() || (! in_parallel()) ); thread_alloc_info* info = thread_info(thread); // do the addition size_t result = info->count_inuse_ + inc; CPPAD_ASSERT_UNKNOWN( result >= info->count_inuse_ ); info->count_inuse_ = result; } // ----------------------------------------------------------------------- /*! Increase the number of bytes of memory that are currently avaialble; i.e., have been obtained obtained from the system and are being held future use. \copydetails inc_inuse */ static void inc_available(size_t inc, size_t thread) { CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS); CPPAD_ASSERT_UNKNOWN( thread == thread_num() || (! in_parallel()) ); thread_alloc_info* info = thread_info(thread); // do the addition size_t result = info->count_available_ + inc; CPPAD_ASSERT_UNKNOWN( result >= info->count_available_ ); info->count_available_ = result; } // ----------------------------------------------------------------------- /*! Decrease the number of bytes of memory that are currently in use; i.e., that been obtained with \c get_memory and not yet returned. \param dec [in] amount to decrease number of bytes in use. \param thread [in] Thread for which we are decreasing the number of bytes in use (must be less than \c num_threads). Durring parallel execution, this must be the thread that is currently executing. */ static void dec_inuse(size_t dec, size_t thread) { CPPAD_ASSERT_UNKNOWN( thread < num_threads() || (! in_parallel()) ); CPPAD_ASSERT_UNKNOWN( thread == thread_num() || (! in_parallel()) ); thread_alloc_info* info = thread_info(thread); // do the subtraction CPPAD_ASSERT_UNKNOWN( info->count_inuse_ >= dec ); info->count_inuse_ = info->count_inuse_ - dec; } // ----------------------------------------------------------------------- /*! Decrease the number of bytes of memory that are currently avaialble; i.e., have been obtained obtained from the system and are being held future use. \copydetails dec_inuse */ static void dec_available(size_t dec, size_t thread) { CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS); CPPAD_ASSERT_UNKNOWN( thread == thread_num() || (! in_parallel()) ); thread_alloc_info* info = thread_info(thread); // do the subtraction CPPAD_ASSERT_UNKNOWN( info->count_available_ >= dec ); info->count_available_ = info->count_available_ - dec; } // ---------------------------------------------------------------------- /*! Set and get the number of threads that are sharing memory. \param number_new If \c number is zero, we are only retreiving the current maximum number of threads. Otherwise, we are setting and retreiving maximum number of threads. \return the number of threads that are sharing memory. If \c number_new is non-zero, the return value is equal to \c number_new. */ static size_t set_get_num_threads(size_t number_new) { static size_t number_user = 1; CPPAD_ASSERT_UNKNOWN( number_new <= CPPAD_MAX_NUM_THREADS ); CPPAD_ASSERT_UNKNOWN( ! in_parallel() || (number_new == 0) ); // case where we are changing the number of threads if( number_new != 0 ) number_user = number_new; return number_user; } /*! Set and call the routine that determine if we are in parallel execution mode. \return value retuned by most recent setting for \a parallel_new. If \a set is true, or the most recent setting is \c CPPAD_NULL (its initial value), the return value is false. Otherwise the function corresponding to the most recent setting is called and its value returned by \c set_get_in_parallel. \param parallel_new [in] If \a set is false, \a parallel_new it is not used. Otherwise, the current value of \c parallel_new becomes the most recent setting for in_parallel. \param set If \a set is true, then \a parallel_new is becomes the most recent setting for this \c set_get_in_parallel. */ static bool set_get_in_parallel( bool (*parallel_new)(void) , bool set = false ) { static bool (*parallel_user)(void) = CPPAD_NULL; if( set ) { parallel_user = parallel_new; return false; } if( parallel_user == CPPAD_NULL ) return false; return parallel_user(); } /*! Set and call the routine that determine the current thread number. \return returns value for the most recent setting for \a thread_num_new. If \a set is true, or the most recent setting is \c CPPAD_NULL (its initial value), the return value is zero. Otherwise the routine corresponding to the most recent setting is called and its value returned by \c set_get_thread_num. \param thread_num_new [in] If \a set is false, \a thread_num_new it is not used. Otherwise, the current value of \c thread_num_new becomes the most recent setting for thread_num. \param set If \a set is true, then \a thread_num_new is becomes the most recent setting for this \c set_get_thread_num. */ static size_t set_get_thread_num( size_t (*thread_num_new)(void) , bool set = false ) { static size_t (*thread_num_user)(void) = CPPAD_NULL; if( set ) { thread_num_user = thread_num_new; return 0; } if( thread_num_user == CPPAD_NULL ) return 0; size_t thread = thread_num_user(); CPPAD_ASSERT_KNOWN( thread < set_get_num_threads(0) , "parallel_setup: thread_num() >= num_threads" ); return thread; } // ============================================================================ public: /* $begin ta_parallel_setup$$ $spell alloc num bool $$ $section Setup thread_alloc For Use in Multi-Threading Environment$$ $index setup, thread_alloc$$ $index thread_alloc, setup$$ $index parallel, setup$$ $index setup, parallel$$ $index num_threads$$ $index in_parallel$$ $index thread_num$$ $index multi-threading, initialize$$ $index initialize, multi-threading$$ $head Syntax$$ $codei%thread_alloc::parallel_setup(%num_threads%, %in_parallel%, %thread_num%) %$$ $head Purpose$$ By default there is only one thread and all execution is in sequential mode, i.e., multiple threads are not sharing the same memory; i.e. not in parallel mode. $head Speed$$ It should be faster, even when $icode num_thread$$ is equal to one, for $code thread_alloc$$ to hold onto memory. This can be accomplished using the function call $codei% thread_alloc::hold_memory(true) %$$ see $cref/hold_memory/ta_hold_memory/$$. $head num_threads$$ This argument has prototype $codei% size_t %num_threads% %$$ and must be greater than zero. It specifies the number of threads that are sharing memory. The case $icode%num_threads% == 1%$$ is a special case that is used to terminate a multi-threading environment. $head in_parallel$$ This function has prototype $codei% bool %in_parallel%(void) %$$ It must return $code true$$ if there is more than one thread currently executing. Otherwise it can return false. $pre $$ In the special case where $icode%num_threads% == 1%$$, the routine $icode in_parallel$$ is not used. $head thread_num$$ This function has prototype $codei% size_t %thread_num%(void) %$$ It must return a thread number that uniquely identifies the currently executing thread. Furthermore $codei% 0 <= %thread_num%() < %num_threads% %$$. In the special case where $icode%num_threads% == 1%$$, the routine $icode thread_num$$ is not used. $pre $$ Note that this function is called by other routines so, as soon as a new thread is executing, one must be certain that $icode thread_num()$$ will work for that thread. $head Restrictions$$ The function $code parallel_setup$$ must be called before the program enters $cref/parallel/ta_in_parallel/$$ execution mode. In addition, this function cannot be called while in parallel mode. $head Example$$ The files $cref simple_ad_openmp.cpp$$, $cref simple_ad_bthread.cpp$$, and $cref simple_ad_pthread.cpp$$, contain examples and tests that use this function. $end */ /*! Set thread_alloc up for parallel mode usage. \param num_threads [in] Is the number of thread that may be executing at the same time. \param in_parallel [in] Is the routine that determines if we are in parallel mode or not. \param thread_num [in] Is the routine that determines the current thread number (between zero and num_threads minus one). */ static void parallel_setup( size_t num_threads , bool (*in_parallel)(void) , size_t (*thread_num)(void) ) { // Special case where we go back to single thread mode right away // (previous settings may no longer be valid) if( num_threads == 1 ) { bool set = true; set_get_num_threads(num_threads); set_get_in_parallel(CPPAD_NULL, set); set_get_thread_num(CPPAD_NULL, set); return; } CPPAD_ASSERT_KNOWN( num_threads <= CPPAD_MAX_NUM_THREADS , "parallel_setup: num_threads is too large" ); CPPAD_ASSERT_KNOWN( num_threads != 0 , "parallel_setup: num_threads == zero" ); CPPAD_ASSERT_KNOWN( in_parallel != CPPAD_NULL , "parallel_setup: num_threads != 1 and in_parallel == CPPAD_NULL" ); CPPAD_ASSERT_KNOWN( thread_num != CPPAD_NULL , "parallel_setup: num_threads != 1 and thread_num == CPPAD_NULL" ); // Make sure that constructors for all static variables in this file // are called in sequential mode. for(size_t thread = 0; thread < num_threads; thread++) thread_info(thread); capacity_info(); size_t cap_bytes; void* v_ptr = get_memory(0, cap_bytes); // free memory allocated by call to get_memory above return_memory(v_ptr); free_available( set_get_thread_num(CPPAD_NULL) ); // delay this so thread_num() call above is in previous mode // (current setings may not yet be valid) if( num_threads > 1 ) { bool set = true; set_get_num_threads(num_threads); set_get_in_parallel(in_parallel, set); set_get_thread_num(thread_num, set); } } /* $begin ta_num_threads$$ $spell inv CppAD num alloc $$ $section Get Number of Threads$$ $index num_threads, thread_alloc$$ $index thread_alloc, num_threads$$ $index threads, number of$$ $head Syntax$$ $icode%number% = thread_alloc::num_threads()%$$ $head Purpose$$ Determine the number of threads as set during $cref/parallel_setup/ta_parallel_setup/$$. $head number$$ The return value $icode number$$ has prototype $codei% size_t %number% %$$ and is equal to the value of $cref/num_threads/ta_parallel_setup/num_threads/$$ in the previous call to $icode parallel_setup$$. If there was no such previous call, the value one is returned. $head Example$$ The example and test $cref thread_alloc.cpp$$ uses this routine. $end */ /*! Get the current number of threads that thread_alloc can use. */ static size_t num_threads(void) { return set_get_num_threads(0); } /* ----------------------------------------------------------------------- $begin ta_in_parallel$$ $section Is The Current Execution in Parallel Mode$$ $spell thread_alloc bool $$ $index in_parallel, thread_alloc$$ $index thread_alloc, in_parallel$$ $index parallel, execution$$ $index execution, parallel$$ $index sequential, execution$$ $head Syntax$$ $icode%flag% = thread_alloc::in_parallel()%$$ $head Purpose$$ Some of the $cref thread_alloc$$ allocation routines have different specifications for parallel (not sequential) execution mode. This routine enables you to determine if the current execution mode is sequential or parallel. $head flag$$ The return value has prototype $codei% bool %flag% %$$ It is true if the current execution is in parallel mode (possibly multi-threaded) and false otherwise (sequential mode). $head Example$$ $cref thread_alloc.cpp$$ $end */ /// Are we in a parallel execution state; i.e., is it possible that /// other threads are currently executing. static bool in_parallel(void) { return set_get_in_parallel(0); } /* ----------------------------------------------------------------------- $begin ta_thread_num$$ $spell CppAD num thread_alloc cppad.hpp $$ $section Get the Current Thread Number$$ $index thread_num, thread_alloc$$ $index thread_alloc, thread_num$$ $index thread, current$$ $index current, thread$$ $head Syntax$$ $icode%thread% = thread_alloc::thread_num()%$$ $head Purpose$$ Some of the $cref thread_alloc$$ allocation routines have a thread number. This routine enables you to determine the current thread. $head thread$$ The return value $icode thread$$ has prototype $codei% size_t %thread% %$$ and is the currently executing thread number. If $code _OPENMP$$ is not defined, $icode thread$$ is zero. $head Example$$ $cref thread_alloc.cpp$$ $end */ /// Get current thread number static size_t thread_num(void) { return set_get_thread_num(CPPAD_NULL); } /* ----------------------------------------------------------------------- $begin ta_get_memory$$ $spell std num ptr thread_alloc $$ $section Get At Least A Specified Amount of Memory$$ $index thread_num, thread_alloc$$ $index thread_alloc, thread_num$$ $index memory, allocate$$ $index allocate, memory$$ $head Syntax$$ $icode%v_ptr% = thread_alloc::get_memory(%min_bytes%, %cap_bytes%)%$$ $head Purpose$$ Use $cref thread_alloc$$ to obtain a minimum number of bytes of memory (for use by the $cref/current thread/ta_thread_num/$$). $head min_bytes$$ This argument has prototype $codei% size_t %min_bytes% %$$ It specifies the minimum number of bytes to allocate. This value must be less than $codep std::numeric_limits::max() / 2 $$ $head cap_bytes$$ This argument has prototype $codei% size_t& %cap_bytes% %$$ It's input value does not matter. Upon return, it is the actual number of bytes (capacity) that have been allocated for use, $codei% %min_bytes% <= %cap_bytes% %$$ $head v_ptr$$ The return value $icode v_ptr$$ has prototype $codei% void* %v_ptr% %$$ It is the location where the $icode cap_bytes$$ of memory that have been allocated for use begins. $head Allocation Speed$$ This allocation should be faster if the following conditions hold: $list number$$ The memory allocated by a previous call to $code get_memory$$ is currently available for use. $lnext The current $icode min_bytes$$ is between the previous $icode min_bytes$$ and previous $icode cap_bytes$$. $lend $head Alignment$$ We call a memory allocation aligned if the address is a multiple of the number of bytes in a $code size_t$$ value. If the system $code new$$ allocator is aligned, then $icode v_ptr$$ pointer is also aligned. $head Example$$ $cref thread_alloc.cpp$$ $end */ /*! Use thread_alloc to get a specified amount of memory. If the memory allocated by a previous call to \c get_memory is now avaialable, and \c min_bytes is between its previous value and the previous \c cap_bytes, this memory allocation will have optimal speed. Otherwise, the memory allocation is more complicated and may have to wait for other threads to complete an allocation. \param min_bytes [in] The minimum number of bytes of memory to be obtained for use. \param cap_bytes [out] The actual number of bytes of memory obtained for use. \return pointer to the beginning of the memory allocated for use. */ static void* get_memory(size_t min_bytes, size_t& cap_bytes) { // see first_trace below CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; // check that number of requested bytes is not to large CPPAD_ASSERT_KNOWN( min_bytes < std::numeric_limits::max() / 2 , "get_memory(min_bytes, cap_bytes): min_bytes is too large" ); size_t num_cap = capacity_info()->number; using std::endl; // determine the capacity for this request size_t c_index = 0; const size_t* capacity_vec = capacity_info()->value; while( capacity_vec[c_index] < min_bytes ) { ++c_index; CPPAD_ASSERT_UNKNOWN(c_index < num_cap ); } cap_bytes = capacity_vec[c_index]; // determine the thread, capacity, and info for this thread size_t thread = thread_num(); size_t tc_index = thread * num_cap + c_index; thread_alloc_info* info = thread_info(thread); # ifndef NDEBUG // trace allocation static bool first_trace = true; if( cap_bytes == CPPAD_TRACE_CAPACITY && thread == CPPAD_TRACE_THREAD && first_trace ) { Rcout << endl; Rcout << "thread_alloc: Trace for Thread = " << thread; Rcout << " and capacity = " << cap_bytes << endl; if( first_trace ) first_trace = false; } // Root nodes for both lists. Note these are different for different // threads because tc_index is different for different threads. block_t* inuse_root = info->root_inuse_ + c_index; # endif block_t* available_root = info->root_available_ + c_index; // check if we already have a node we can use void* v_node = available_root->next_; block_t* node = reinterpret_cast(v_node); if( node != CPPAD_NULL ) { CPPAD_ASSERT_UNKNOWN( node->tc_index_ == tc_index ); // remove node from available list available_root->next_ = node->next_; // return value for get_memory void* v_ptr = reinterpret_cast(node + 1); # ifndef NDEBUG // add node to inuse list node->next_ = inuse_root->next_; inuse_root->next_ = v_node; // trace allocation if( cap_bytes == CPPAD_TRACE_CAPACITY && thread == CPPAD_TRACE_THREAD ) { Rcout << "get_memory: v_ptr = " << v_ptr << endl; } # endif // adjust counts inc_inuse(cap_bytes, thread); dec_available(cap_bytes, thread); // return pointer to memory, do not inclue thread_alloc information return v_ptr; } // Create a new node with thread_alloc information at front. // This uses the system allocator, which is thread safe, but slower, // because the thread might wait for a lock on the allocator. v_node = ::operator new(sizeof(block_t) + cap_bytes); node = reinterpret_cast(v_node); node->tc_index_ = tc_index; void* v_ptr = reinterpret_cast(node + 1); # ifndef NDEBUG // add node to inuse list node->next_ = inuse_root->next_; inuse_root->next_ = v_node; // trace allocation if( cap_bytes == CPPAD_TRACE_CAPACITY && thread == CPPAD_TRACE_THREAD ) { Rcout << "get_memory: v_ptr = " << v_ptr << endl; } # endif // adjust counts inc_inuse(cap_bytes, thread); return v_ptr; } /* ----------------------------------------------------------------------- $begin ta_return_memory$$ $spell num ptr thread_alloc $$ $section Return Memory to thread_alloc$$ $index return_memory, thread_alloc$$ $index thread_alloc, return_memory$$ $index memory, available$$ $index available, memory$$ $index thread, available memory$$ $head Syntax$$ $codei%thread_alloc::return_memory(%v_ptr%)%$$ $head Purpose$$ If $cref/hold_memory/ta_hold_memory/$$ is false, the memory is returned to the system. Otherwise, the memory is retained by $cref thread_alloc$$ for quick future use by the thread that allocated to memory. $head v_ptr$$ This argument has prototype $codei% void* %v_ptr% %$$. It must be a pointer to memory that is currently in use; i.e. obtained by a previous call to $cref/get_memory/ta_get_memory/$$ and not yet returned. $head Thread$$ Either the $cref/current thread/ta_thread_num/$$ must be the same as during the corresponding call to $cref/get_memory/ta_get_memory/$$, or the current execution mode must be sequential (not $cref/parallel/ta_in_parallel/$$). $head NDEBUG$$ If $code NDEBUG$$ is defined, $icode v_ptr$$ is not checked (this is faster). Otherwise, a list of in use pointers is searched to make sure that $icode v_ptr$$ is in the list. $head Example$$ $cref thread_alloc.cpp$$ $end */ /*! Return memory that was obtained by \c get_memory. If num_threads() == 1, the memory is returned to the system. Otherwise, it is retained by \c thread_alloc and available for use by \c get_memory for this thread. \param v_ptr [in] Value of the pointer returned by \c get_memory and still in use. After this call, this pointer will available (and not in use). \par We must either be in sequential (not parallel) execution mode, or the current thread must be the same as for the corresponding call to \c get_memory. */ static void return_memory(void* v_ptr) { size_t num_cap = capacity_info()->number; block_t* node = reinterpret_cast(v_ptr) - 1; size_t tc_index = node->tc_index_; size_t thread = tc_index / num_cap; size_t c_index = tc_index % num_cap; size_t capacity = capacity_info()->value[c_index]; CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS ); CPPAD_ASSERT_KNOWN( thread == thread_num() || (! in_parallel()), "Attempt to return memory for a different thread " "while in parallel mode" ); thread_alloc_info* info = thread_info(thread); # ifndef NDEBUG // remove node from inuse list void* v_node = reinterpret_cast(node); block_t* inuse_root = info->root_inuse_ + c_index; block_t* previous = inuse_root; while( (previous->next_ != CPPAD_NULL) & (previous->next_ != v_node) ) previous = reinterpret_cast(previous->next_); // check that v_ptr is valid if( previous->next_ != v_node ) { using std::endl; std::ostringstream oss; oss << "return_memory: attempt to return memory not in use"; oss << endl; oss << "v_ptr = " << v_ptr << endl; oss << "thread = " << thread << endl; oss << "capacity = " << capacity << endl; oss << "See CPPAD_TRACE_THREAD & CPPAD_TRACE_CAPACITY in"; oss << endl << "# include " << endl; CPPAD_ASSERT_KNOWN(false, oss.str().c_str() ); } // trace option if( capacity==CPPAD_TRACE_CAPACITY && thread==CPPAD_TRACE_THREAD ) { Rcout << "return_memory: v_ptr = " << v_ptr << std::endl; } // remove v_ptr from inuse list previous->next_ = node->next_; # endif // capacity bytes are removed from the inuse pool dec_inuse(capacity, thread); // check for case where we just return the memory to the system if( ! set_get_hold_memory(false) ) { ::operator delete( reinterpret_cast(node) ); return; } // add this node to available list for this thread and capacity block_t* available_root = info->root_available_ + c_index; node->next_ = available_root->next_; available_root->next_ = reinterpret_cast(node); // capacity bytes are added to the available pool inc_available(capacity, thread); } /* ----------------------------------------------------------------------- $begin ta_free_available$$ $spell num thread_alloc $$ $section Free Memory Currently Available for Quick Use by a Thread$$ $spell inuse $$ $index free_available, thread_alloc$$ $index thread_alloc, free_available$$ $index free, available$$ $index available, free$$ $index thread, free memory$$ $head Syntax$$ $codei%thread_alloc::free_available(%thread%)%$$ $head Purpose$$ Return to the system all the memory that is currently being $cref/held/ta_hold_memory/$$ for quick use by the specified thread. $subhead Extra Memory$$ In the case where $icode%thread% > 0%$$, some extra memory is used to track allocations by the specified thread. If $codei% thread_alloc::inuse(%thread%) == 0 %$$ the extra memory is also returned to the system. $head thread$$ This argument has prototype $codei% size_t %thread% %$$ Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$, or the current execution mode must be sequential (not $cref/parallel/ta_in_parallel/$$). $head Example$$ $cref thread_alloc.cpp$$ $end */ /*! Return all the memory being held as available for a thread to the system. \param thread [in] this thread that will no longer have any available memory after this call. This must either be the thread currently executing, or we must be in sequential (not parallel) execution mode. */ static void free_available(size_t thread) { CPPAD_ASSERT_KNOWN( thread < CPPAD_MAX_NUM_THREADS, "Attempt to free memory for a thread >= CPPAD_MAX_NUM_THREADS" ); CPPAD_ASSERT_KNOWN( thread == thread_num() || (! in_parallel()), "Attempt to free memory for a different thread " "while in parallel mode" ); size_t num_cap = capacity_info()->number; if( num_cap == 0 ) return; const size_t* capacity_vec = capacity_info()->value; size_t c_index; thread_alloc_info* info = thread_info(thread); for(c_index = 0; c_index < num_cap; c_index++) { size_t capacity = capacity_vec[c_index]; block_t* available_root = info->root_available_ + c_index; void* v_ptr = available_root->next_; while( v_ptr != CPPAD_NULL ) { block_t* node = reinterpret_cast(v_ptr); void* next = node->next_; ::operator delete(v_ptr); v_ptr = next; dec_available(capacity, thread); } available_root->next_ = CPPAD_NULL; } CPPAD_ASSERT_UNKNOWN( available(thread) == 0 ); if( inuse(thread) == 0 ) { // clear the information for this thread thread_info(thread, true); } } /* ----------------------------------------------------------------------- $begin ta_hold_memory$$ $spell alloc num $$ $section Control When Thread Alloc Retains Memory For Future Use$$ $index thread_alloc, hold memory$$ $index hold, thread_alloc memory$$ $index memory, thread_alloc hold$$ $head Syntax$$ $codei%thread_alloc::hold_memory(%value%)%$$ $head Purpose$$ It should be faster, even when $icode num_thread$$ is equal to one, for $code thread_alloc$$ to hold onto memory. Calling $icode hold_memory$$ with $icode value$$ equal to true, instructs $code thread_alloc$$ to hold onto memory, and put it in the $cref/available/ta_available/$$ pool, after each call to $cref/return_memory/ta_return_memory/$$. $head value$$ If $icode value$$ is true, $code thread_alloc$$ with hold onto memory for future quick use. If it is false, future calls to $cref/return_memory/ta_return_memory/$$ will return the corresponding memory to the system. By default (when $code hold_memory$$ has not been called) $code thread_alloc$$ does not hold onto memory. $head free_available$$ Memory that is being held by $code thread_alloc$$ can be returned to the system using $cref/free_available/ta_free_available/$$. $end */ /*! Change the thread_alloc hold memory setting. \param value [in] New value for the thread_alloc hold memory setting. */ static void hold_memory(bool value) { bool set = true; set_get_hold_memory(set, value); } /* ----------------------------------------------------------------------- $begin ta_inuse$$ $spell num inuse thread_alloc $$ $section Amount of Memory a Thread is Currently Using$$ $index inuse, thread_alloc$$ $index thread_alloc, inuse$$ $index use, memory$$ $index thread, memory inuse$$ $head Syntax$$ $icode%num_bytes% = thread_alloc::inuse(%thread%)%$$ $head Purpose$$ Memory being managed by $cref thread_alloc$$ has two states, currently in use by the specified thread, and quickly available for future use by the specified thread. This function informs the program how much memory is in use. $head thread$$ This argument has prototype $codei% size_t %thread% %$$ Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$, or the current execution mode must be sequential (not $cref/parallel/ta_in_parallel/$$). $head num_bytes$$ The return value has prototype $codei% size_t %num_bytes% %$$ It is the number of bytes currently in use by the specified thread. $head Example$$ $cref thread_alloc.cpp$$ $end */ /*! Determine the amount of memory that is currently inuse. \param thread [in] Thread for which we are determining the amount of memory (must be < CPPAD_MAX_NUM_THREADS). Durring parallel execution, this must be the thread that is currently executing. \return The amount of memory in bytes. */ static size_t inuse(size_t thread) { CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS); CPPAD_ASSERT_UNKNOWN( thread == thread_num() || (! in_parallel()) ); thread_alloc_info* info = thread_info(thread); return info->count_inuse_; } /* ----------------------------------------------------------------------- $begin ta_available$$ $spell num thread_alloc $$ $section Amount of Memory Available for Quick Use by a Thread$$ $index available, thread_alloc$$ $index thread_alloc, available$$ $index memory, available$$ $index thread, available memory$$ $head Syntax$$ $icode%num_bytes% = thread_alloc::available(%thread%)%$$ $head Purpose$$ Memory being managed by $cref thread_alloc$$ has two states, currently in use by the specified thread, and quickly available for future use by the specified thread. This function informs the program how much memory is available. $head thread$$ This argument has prototype $codei% size_t %thread% %$$ Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$, or the current execution mode must be sequential (not $cref/parallel/ta_in_parallel/$$). $head num_bytes$$ The return value has prototype $codei% size_t %num_bytes% %$$ It is the number of bytes currently available for use by the specified thread. $head Example$$ $cref thread_alloc.cpp$$ $end */ /*! Determine the amount of memory that is currently available for use. \copydetails inuse */ static size_t available(size_t thread) { CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS); CPPAD_ASSERT_UNKNOWN( thread == thread_num() || (! in_parallel()) ); thread_alloc_info* info = thread_info(thread); return info->count_available_; } /* ----------------------------------------------------------------------- $begin ta_create_array$$ $spell inuse thread_alloc sizeof $$ $section Allocate An Array and Call Default Constructor for its Elements$$ $index create_array, thread_alloc$$ $index thread_alloc, create_array$$ $index array, allocate$$ $index allocate, array$$ $head Syntax$$ $icode%array% = thread_alloc::create_array<%Type%>(%size_min%, %size_out%)%$$. $head Purpose$$ Create a new raw array using $cref thread_alloc$$ memory allocator (works well in a multi-threading environment) and call default constructor for each element. $head Type$$ The type of the elements of the array. $head size_min$$ This argument has prototype $codei% size_t %size_min% %$$ This is the minimum number of elements that there can be in the resulting $icode array$$. $head size_out$$ This argument has prototype $codei% size_t& %size_out% %$$ The input value of this argument does not matter. Upon return, it is the actual number of elements in $icode array$$ ($icode% size_min %<=% size_out%$$). $head array$$ The return value $icode array$$ has prototype $codei% %Type%* %array% %$$ It is array with $icode size_out$$ elements. The default constructor for $icode Type$$ is used to initialize the elements of $icode array$$. Note that $cref/delete_array/ta_delete_array/$$ should be used to destroy the array when it is no longer needed. $head Delta$$ The amount of memory $cref/inuse/ta_inuse/$$ by the current thread, will increase $icode delta$$ where $codei% sizeof(%Type%) * (%size_out% + 1) > %delta% >= sizeof(%Type%) * %size_out% %$$ The $cref/available/ta_available/$$ memory will decrease by $icode delta$$, (and the allocation will be faster) if a previous allocation with $icode size_min$$ between its current value and $icode size_out$$ is available. $head Alignment$$ We call a memory allocation aligned if the address is a multiple of the number of bytes in a $code size_t$$ value. If the system $code new$$ allocator is aligned, then $icode array$$ pointer is also aligned. $head Example$$ $cref thread_alloc.cpp$$ $end */ /*! Use thread_alloc to allocate an array, then call default construtor for each element. \tparam Type The type of the elements of the array. \param size_min [in] The minimum number of elements in the array. \param size_out [out] The actual number of elements in the array. \return pointer to the first element of the array. The default constructor is used to initialize all the elements of the array. \par The \c extra_ field, in the \c thread_alloc node before the return value, is set to size_out. */ template static Type* create_array(size_t size_min, size_t& size_out) { // minimum number of bytes to allocate size_t min_bytes = size_min * sizeof(Type); // do the allocation size_t num_bytes; void* v_ptr = get_memory(min_bytes, num_bytes); // This is where the array starts Type* array = reinterpret_cast(v_ptr); // number of Type values in the allocation size_out = num_bytes / sizeof(Type); // store this number in the extra field block_t* node = reinterpret_cast(v_ptr) - 1; node->extra_ = size_out; // call default constructor for each element if(!isDouble::value){ size_t i; for(i = 0; i < size_out; i++) new(array + i) Type(); } return array; } /* ----------------------------------------------------------------------- $begin ta_delete_array$$ $spell inuse thread_alloc sizeof deallocate $$ $section Deallocate An Array and Call Destructor for its Elements$$ $index delete_array, thread_alloc$$ $index thread_alloc, delete_array$$ $index array, allocate$$ $index allocate, array$$ $head Syntax$$ $codei%thread_alloc::delete_array(%array%)%$$. $head Purpose$$ Returns memory corresponding to an array created by (create by $cref/create_array/ta_create_array/$$) to the $cref/available/ta_available/$$ memory pool for the current thread. $head Type$$ The type of the elements of the array. $head array$$ The argument $icode array$$ has prototype $codei% %Type%* %array% %$$ It is a value returned by $cref/create_array/ta_create_array/$$ and not yet deleted. The $icode Type$$ destructor is called for each element in the array. $head Thread$$ The $cref/current thread/ta_thread_num/$$ must be the same as when $cref/create_array/ta_create_array/$$ returned the value $icode array$$. There is an exception to this rule: when the current execution mode is sequential (not $cref/parallel/ta_in_parallel/$$) the current thread number does not matter. $head Delta$$ The amount of memory $cref/inuse/ta_inuse/$$ will decrease by $icode delta$$, and the $cref/available/ta_available/$$ memory will increase by $icode delta$$, where $cref/delta/ta_create_array/Delta/$$ is the same as for the corresponding call to $code create_array$$. $head Example$$ $cref thread_alloc.cpp$$ $end */ /*! Return Memory Used for an Array to the Available Pool (include destructor call for each element). \tparam Type The type of the elements of the array. \param array [in] A value returned by \c create_array that has not yet been deleted. The \c Type destructor is used to destroy each of the elements of the array. \par Durring parallel execution, the current thread must be the same as during the corresponding call to \c create_array. */ template static void delete_array(Type* array) { // determine the number of values in the array block_t* node = reinterpret_cast(array) - 1; size_t size = node->extra_; // call destructor for each element if(!isDouble::value){ size_t i; for(i = 0; i < size; i++) (array + i)->~Type(); } // return the memory to the available pool for this thread thread_alloc::return_memory( reinterpret_cast(array) ); } /* ----------------------------------------------------------------------- $begin ta_free_all$$ $spell alloc bool inuse $$ $section Free All Memory That Was Allocated for Use by thread_alloc$$ $index free, all thread_alloc$$ $index thread_alloc, free all$$ $head Syntax$$ $icode%ok% = thread_alloc::free_all()%$$. $head Purpose$$ Returns all memory that was used by $code thread_alloc$$ to the system. $head ok$$ The return value $icode ok$$ has prototype $codei% bool %ok% %$$ Its value will be $code true$$ if all the memory can be freed. This requires that for all $icode thread$$ indices, there is no memory $cref/inuse/ta_inuse/$$; i.e., $codei% 0 == thread_alloc::inuse(%thread%) %$$ Otherwise, the return value will be false. $head Restrictions$$ This function cannot be called while in parallel mode. $head Example$$ $cref thread_alloc.cpp$$ $end */ /*! Return to the system all thread_alloc memory that is not currently inuse. \return If no \c thread_alloc memory is currently inuse, all memory is returned to the system and the return value is true. Otherwise the return value is false. */ static bool free_all(void) { CPPAD_ASSERT_KNOWN( ! in_parallel(), "free_all cannot be used while in parallel execution" ); bool ok = true; size_t thread = CPPAD_MAX_NUM_THREADS; while(thread--) { ok &= inuse(thread) == 0; free_available(thread); } return ok; } }; } // END_CPPAD_NAMESPACE // preprocessor symbols local to this file # undef CPPAD_MAX_NUM_CAPACITY # undef CPPAD_MIN_DOUBLE_CAPACITY # undef CPPAD_TRACE_CAPACITY # undef CPPAD_TRACE_THREAD # endif TMB/inst/include/cppad/PowInt.h0000644000176200001440000000005114113627761015760 0ustar liggesusers/* $Id$ */ # include "cppad/pow_int.hpp" TMB/inst/include/cppad/check_simple_vector.hpp0000644000176200001440000001167714536067012021124 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_CHECK_SIMPLE_VECTOR_INCLUDED # define CPPAD_CHECK_SIMPLE_VECTOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin CheckSimpleVector$$ $spell alloc const cppad.hpp CppAD $$ $section Check Simple Vector Concept$$ $index simple, vector check$$ $index vector, simple check$$ $index check, simple vector$$ $index concept, check simple vector$$ $head Syntax$$ $code # include $$ $pre $$ $codei%CheckSimpleVector<%Scalar%, %Vector%>()%$$ $pre $$ $codei%CheckSimpleVector<%Scalar%, %Vector%>(%x%, %y%)%$$ $head Purpose$$ Preforms compile and run time checks that the type specified by $icode Vector$$ satisfies all the requirements for a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Scalar$$. If a requirement is not satisfied, a an error message makes it clear what condition is not satisfied. $head x, y$$ If the arguments $icode x$$ and $icode y$$ are present, they have prototype $codei% const %Scalar%& %x% const %Scalar%& %y% %$$ In addition, the check $codei% %x% == %x% %$$ will return the boolean value $code true$$, and $codei% %x% == %y% %$$ will return $code false$$. $head Restrictions$$ If the arguments $icode x$$ and $icode y$$ are not present, the following extra assumption is made by $code CheckSimpleVector$$: If $icode x$$ is a $icode Scalar$$ object $codei% %x% = 0 %y% = 1 %$$ assigns values to the objects $icode x$$ and $icode y$$. In addition, $icode%x% == %x%$$ would return the boolean value $code true$$ and $icode%x% == %y%$$ would return $code false$$. $head Include$$ The file $code cppad/check_simple_vector.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest if the CppAD include files. $head Parallel Mode$$ $index parallel, CheckSimpleVector$$ $index CheckSimpleVector, parallel$$ The routine $cref/thread_alloc::parallel_setup/ta_parallel_setup/$$ must be called before it can be used in $cref/parallel/ta_in_parallel/$$ mode. $head Example$$ $children% example/check_simple_vector.cpp %$$ The file $cref check_simple_vector.cpp$$ contains an example and test of this function where $icode S$$ is the same as $icode T$$. It returns true, if it succeeds an false otherwise. The comments in this example suggest a way to change the example so $icode S$$ is not the same as $icode T$$. $end --------------------------------------------------------------------------- */ # include # include # include # include namespace CppAD { # ifdef NDEBUG template inline void CheckSimpleVector(const Scalar& x, const Scalar& y) { } template inline void CheckSimpleVector(void) { } # else template struct ok_if_S_same_as_T { }; template struct ok_if_S_same_as_T { T value; }; template void CheckSimpleVector(const Scalar& x, const Scalar& y) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL static size_t count; if( count > 0 ) return; count++; // value_type must be type of elements of Vector typedef typename Vector::value_type value_type; // check that elements of Vector have type Scalar struct ok_if_S_same_as_T x_copy; x_copy.value = x; // check default constructor Vector d; // size member function CPPAD_ASSERT_KNOWN( d.size() == 0, "default construtor result does not have size zero" ); // resize to same size as other vectors in test d.resize(1); // check sizing constructor Vector s(1); // check element assignment s[0] = y; CPPAD_ASSERT_KNOWN( s[0] == y, "element assignment failed" ); // check copy constructor s[0] = x_copy.value; const Vector c(s); s[0] = y; CPPAD_ASSERT_KNOWN( c[0] == x, "copy constructor is shallow" ); // vector assignment operator d[0] = x; s = d; s[0] = y; CPPAD_ASSERT_KNOWN( d[0] == x, "assignment operator is shallow" ); // element access, right side const // element assignment, left side not const d[0] = c[0]; CPPAD_ASSERT_KNOWN( d[0] == x, "element assignment from const failed" ); } template void CheckSimpleVector(void) { Scalar x; Scalar y; // use assignment and not constructor x = 0; y = 1; CheckSimpleVector(x, y); } # endif } // end namespace CppAD # endif TMB/inst/include/cppad/memory_leak.hpp0000644000176200001440000001511314536067012017405 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_MEMORY_LEAK_INCLUDED # define CPPAD_MEMORY_LEAK_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin memory_leak$$ $spell num alloc hpp bool inuse $$ $section Memory Leak Detection$$ $index memory_leak$$ $index leak, memory$$ $index check, memory leak$$ $index static, memory leak check$$ $head Deprecated$$ $index deprecated, memory leak$$ This routine has been deprecated. You should instead use the routine $cref ta_free_all$$. $head Syntax$$ $icode%flag% = %memory_leak() %$$ $icode%flag% = %memory_leak(%add_static%)%$$ $head Purpose$$ This routine checks that the are no memory leaks caused by improper use of $cref thread_alloc$$ memory allocator. The deprecated memory allocator $cref TrackNewDel$$ is also checked. Memory errors in the deprecated $cref omp_alloc$$ allocator are reported as being in $code thread_alloc$$. $head thread$$ It is assumed that $cref/in_parallel()/ta_in_parallel/$$ is false and $cref/thread_num/ta_thread_num/$$ is zero when $code memory_leak$$ is called. $head add_static$$ This argument has prototype $codei% size_t %add_static% %$$ and its default value is zero. Static variables hold onto memory forever. If the argument $icode add_static$$ is present (and non-zero), $code memory_leak$$ adds this amount of memory to the $cref/inuse/ta_inuse/$$ sum that corresponds to static variables in the program. A call with $icode add_static$$ should be make after a routine that has static variables which use $cref/get_memory/ta_get_memory/$$ to allocate memory. The value of $icode add_static$$ should be the difference of $codei% thread_alloc::inuse(0) %$$ before and after the call. Since multiple statics may be allocated in different places in the program, it is expected that there will be multiple calls that use this option. $head flag$$ The return value $icode flag$$ has prototype $codei% bool %flag% %$$ If $icode add_static$$ is non-zero, the return value for $code memory_leak$$ is false. Otherwise, the return value for $code memory_leak$$ should be false (indicating that the only allocated memory corresponds to static variables). $head inuse$$ It is assumed that, when $code memory_leak$$ is called, there should not be any memory $cref/inuse/ta_inuse/$$ or $cref omp_inuse$$ for any thread (except for inuse memory corresponding to static variables). If there is, a message is printed and $code memory_leak$$ returns false. $head available$$ It is assumed that, when $code memory_leak$$ is called, there should not be any memory $cref/available/ta_available/$$ or $cref omp_available$$ for any thread; i.e., it all has been returned to the system. If there is memory still available for any thread, $code memory_leak$$ returns false. $head TRACK_COUNT$$ It is assumed that, when $code memory_leak$$ is called, $cref/TrackCount/TrackNewDel/TrackCount/$$ will return a zero value. If it returns a non-zero value, $code memory_leak$$ returns false. $head Error Message$$ If this is the first call to $code memory_leak$$, no message is printed. Otherwise, if it returns true, an error message is printed to standard output describing the memory leak that was detected. $end */ # include # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file memory_leak.hpp File that implements a memory check at end of a CppAD program */ /*! Function that checks allocator \c thread_alloc for misuse that results in memory leaks. Deprecated routines in track_new_del.hpp and omp_alloc.hpp are also checked. \param add_static [in] The amount specified by \c add_static is added to the amount of memory that is expected to be used by thread zero for static variables. \return If \c add_static is non-zero, the return value is \c false. Otherwise, if one of the following errors is detected, the return value is \c true: \li Thread zero does not have the expected amount of inuse memory (for static variables). \li A thread, other than thread zero, has any inuse memory. \li Any thread has available memory. \par If an error is detected, diagnostic information is printed to standard output. */ inline bool memory_leak(size_t add_static = 0) { // CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL not necessary given asserts below static size_t thread_zero_static_inuse = 0; using std::endl; using CppAD::thread_alloc; using CppAD::omp_alloc; // -------------------------------------------------------------------- CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel(), "memory_leak: in_parallel() is true." ); CPPAD_ASSERT_KNOWN( thread_alloc::thread_num() == 0, "memory_leak: thread_num() is not zero." ); if( add_static != 0 ) { thread_zero_static_inuse += add_static; return false; } bool leak = false; size_t thread = 0; // check that memory in use for thread zero corresponds to statics size_t num_bytes = thread_alloc::inuse(thread); if( num_bytes != thread_zero_static_inuse ) { leak = true; Rcout << "thread zero: static inuse = " << thread_zero_static_inuse; Rcout << "current inuse(thread) = " << num_bytes << endl; } // check that no memory is currently available for this thread num_bytes = thread_alloc::available(thread); if( num_bytes != 0 ) { leak = true; Rcout << "thread zero: available = "; Rcout << num_bytes << endl; } for(thread = 1; thread < CPPAD_MAX_NUM_THREADS; thread++) { // check that no memory is currently in use for this thread num_bytes = thread_alloc::inuse(thread); if( num_bytes != 0 ) { leak = true; Rcout << "thread " << thread << ": inuse(thread) = "; Rcout << num_bytes << endl; } // check that no memory is currently available for this thread num_bytes = thread_alloc::available(thread); if( num_bytes != 0 ) { leak = true; Rcout << "thread " << thread << ": available(thread) = "; Rcout << num_bytes << endl; } } // ---------------------------------------------------------------------- // check track_new_del if( CPPAD_TRACK_COUNT() != 0 ) { leak = true; CppAD::TrackElement::Print(); } return leak; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/error_handler.hpp0000644000176200001440000001367214536067012017737 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ERROR_HANDLER_INCLUDED # define CPPAD_ERROR_HANDLER_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ErrorHandler$$ $spell cppad.hpp CppAD exp bool const $$ $section Replacing the CppAD Error Handler$$ $index error, handler$$ $index handler, error$$ $index replace, error handler$$ $index assert, error handler$$ $index exception, error handler$$ $head Syntax$$ $codei%ErrorHandler %info%(%handler%) %$$ $codei%ErrorHandler::Call(%known%, %line%, %file%, %exp%, %msg%) %$$ $head Constructor$$ When you construct a $code ErrorHandler$$ object, the current CppAD error handler is replaced by $icode handler$$. When the object is destructed, the previous CppAD error handler is restored. $subhead Parallel Mode$$ $index parallel, ErrorHandler$$ $index ErrorHandler, parallel$$ The $code ErrorHandler$$ constructor and destructor cannot be called in $cref/parallel/ta_in_parallel/$$ execution mode. Furthermore, this rule is not abided by, a raw C++ $code assert$$, instead of one that uses this error handler, will be generated. $head Call$$ When $code ErrorHandler::Call$$ is called, the current CppAD error handler is used to report an error. This starts out as a default error handler and can be replaced using the $code ErrorHandler$$ constructor. $head info$$ The object $icode info$$ is used to store information that is necessary to restore the previous CppAD error handler. This is done when the destructor for $icode info$$ is called. $head handler$$ The argument $icode handler$$ has prototype $codei% void (*%handler%) (bool, int, const char *, const char *, const char *); %$$ When an error is detected, it is called with the syntax $codei% %handler% (%known%, %line%, %file%, %exp%, %msg%) %$$ This routine should not return; i.e., upon detection of the error, the routine calling $icode handler$$ does not know how to proceed. $head known$$ The $icode handler$$ argument $icode known$$ has prototype $codei% bool %known% %$$ If it is true, the error being reported is from a know problem. $head line$$ The $icode handler$$ argument $icode line$$ has prototype $codei% int %line% %$$ It reports the source code line number where the error is detected. $head file$$ The $icode handler$$ argument $icode file$$ has prototype $codei% const char *%file% %$$ and is a $code '\0'$$ terminated character vector. It reports the source code file where the error is detected. $head exp$$ The $icode handler$$ argument $icode exp$$ has prototype $codei% const char *%exp% %$$ and is a $code '\0'$$ terminated character vector. It is a source code boolean expression that should have been true, but is false, and thereby causes this call to $icode handler$$. $head msg$$ The $icode handler$$ argument $icode msg$$ has prototype $codei% const char *%msg% %$$ and is a $code '\0'$$ terminated character vector. It reports the meaning of the error from the C++ programmers point of view. $children% example/error_handler.cpp% cppad/local/cppad_assert.hpp %$$ $head Example$$ The file $cref error_handler.cpp$$ contains an example and test a test of using this routine. It returns true if it succeeds and false otherwise. $end --------------------------------------------------------------------------- */ # include # ifdef _OPENMP # include # endif # include # include # include # include // Cannot use the CPPAD_ASSERT_* macros here because they inturn use the // error handler. So this code generates a raw assert. # ifdef _OPENMP # include # define CPPAD_ASSERT_NOT_PARALLEL \ assert( ! omp_in_parallel() ); # else # define CPPAD_ASSERT_NOT_PARALLEL # endif namespace CppAD { // BEGIN CppAD namespace class ErrorHandler { template friend void parallel_ad(void); public: typedef void (*Handler) (bool, int, const char *, const char *, const char *); // construct an handler ErrorHandler(Handler handler) : previous( Current() ) { CPPAD_ASSERT_NOT_PARALLEL; Current() = handler; } // destructor for an error handler ~ErrorHandler(void) { CPPAD_ASSERT_NOT_PARALLEL; Current() = previous; } // report an error static void Call( bool known, int line , const char *file , const char *exp , const char *msg ) { Handler handler = Current(); handler(known, line, file, exp, msg); } private: const Handler previous; // The default error handler static void Default( bool known, int line , const char *file , const char *exp , const char *msg ) { using std::cerr; using std::endl; cerr << CPPAD_PACKAGE_STRING; if( known ) cerr << " error from a known source:" << endl; else cerr << " error from unknown source" << endl; if( msg[0] != '\0' ) cerr << msg << endl; cerr << "Error detected by false result for" << endl; cerr << " " << exp << endl; cerr << "at line " << line << " in the file " << endl; cerr << " " << file << endl; // terminate program execution assert(false); // termination when NDEBUG is defined std::exit(1); } // current error handler static Handler &Current(void) { # ifndef NDEBUG # ifdef _OPENMP // This assert would be a CppAD error (not user error) static bool first_call = true; if( first_call ) { assert( ! omp_in_parallel() ); first_call = false; } # endif # endif static Handler current = Default; return current; } }; } // END CppAD namespace # endif TMB/inst/include/cppad/lu_factor.hpp0000644000176200001440000002700014536067012017055 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_LU_FACTOR_INCLUDED # define CPPAD_LU_FACTOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin LuFactor$$ $escape #$$ $spell cppad.hpp Cpp Geq Lu bool const ip jp namespace std typename $$ $index LuFactor$$ $index linear, Lu factor equation$$ $index equation, Lu factor$$ $index determinant, Lu factor$$ $index solve, Lu factor$$ $section LU Factorization of A Square Matrix$$ $pre $$ $head Syntax$$ $code# include $$ $pre $$ $icode%sign% = LuFactor(%ip%, %jp%, %LU%)%$$ $head Description$$ Computes an LU factorization of the matrix $icode A$$ where $icode A$$ is a square matrix. $head Include$$ The file $code cppad/lu_factor.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Matrix Storage$$ All matrices are stored in row major order. To be specific, if $latex Y$$ is a vector that contains a $latex p$$ by $latex q$$ matrix, the size of $latex Y$$ must be equal to $latex p * q $$ and for $latex i = 0 , \ldots , p-1$$, $latex j = 0 , \ldots , q-1$$, $latex \[ Y_{i,j} = Y[ i * q + j ] \] $$ $head sign$$ The return value $icode sign$$ has prototype $codei% int %sign% %$$ If $icode A$$ is invertible, $icode sign$$ is plus or minus one and is the sign of the permutation corresponding to the row ordering $icode ip$$ and column ordering $icode jp$$. If $icode A$$ is not invertible, $icode sign$$ is zero. $head ip$$ The argument $icode ip$$ has prototype $codei% %SizeVector% &%ip% %$$ (see description of $cref/SizeVector/LuFactor/SizeVector/$$ below). The size of $icode ip$$ is referred to as $icode n$$ in the specifications below. The input value of the elements of $icode ip$$ does not matter. The output value of the elements of $icode ip$$ determine the order of the rows in the permuted matrix. $head jp$$ The argument $icode jp$$ has prototype $codei% %SizeVector% &%jp% %$$ (see description of $cref/SizeVector/LuFactor/SizeVector/$$ below). The size of $icode jp$$ must be equal to $icode n$$. The input value of the elements of $icode jp$$ does not matter. The output value of the elements of $icode jp$$ determine the order of the columns in the permuted matrix. $head LU$$ The argument $icode LU$$ has the prototype $codei% %FloatVector% &%LU% %$$ and the size of $icode LU$$ must equal $latex n * n$$ (see description of $cref/FloatVector/LuFactor/FloatVector/$$ below). $subhead A$$ We define $icode A$$ as the matrix corresponding to the input value of $icode LU$$. $subhead P$$ We define the permuted matrix $icode P$$ in terms of $icode A$$ by $codei% %P%(%i%, %j%) = %A%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ $subhead L$$ We define the lower triangular matrix $icode L$$ in terms of the output value of $icode LU$$. The matrix $icode L$$ is zero above the diagonal and the rest of the elements are defined by $codei% %L%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ for $latex i = 0 , \ldots , n-1$$ and $latex j = 0 , \ldots , i$$. $subhead U$$ We define the upper triangular matrix $icode U$$ in terms of the output value of $icode LU$$. The matrix $icode U$$ is zero below the diagonal, one on the diagonal, and the rest of the elements are defined by $codei% %U%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ for $latex i = 0 , \ldots , n-2$$ and $latex j = i+1 , \ldots , n-1$$. $subhead Factor$$ If the return value $icode sign$$ is non-zero, $codei% %L% * %U% = %P% %$$ If the return value of $icode sign$$ is zero, the contents of $icode L$$ and $icode U$$ are not defined. $subhead Determinant$$ $index determinant$$ If the return value $icode sign$$ is zero, the determinant of $icode A$$ is zero. If $icode sign$$ is non-zero, using the output value of $icode LU$$ the determinant of the matrix $icode A$$ is equal to $codei% %sign% * %LU%[%ip%[0], %jp%[0]] * %...% * %LU%[%ip%[%n%-1], %jp%[%n%-1]] %$$ $head SizeVector$$ The type $icode SizeVector$$ must be a $cref SimpleVector$$ class with $cref/elements of type size_t/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head FloatVector$$ The type $icode FloatVector$$ must be a $cref/simple vector class/SimpleVector/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Float$$ This notation is used to denote the type corresponding to the elements of a $icode FloatVector$$. The type $icode Float$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, the following operations must be defined for any pair of $icode Float$$ objects $icode x$$ and $icode y$$: $table $bold Operation$$ $cnext $bold Description$$ $rnext $codei%log(%x%)%$$ $cnext returns the logarithm of $icode x$$ as a $icode Float$$ object $tend $head AbsGeq$$ Including the file $code lu_factor.hpp$$ defines the template function $codei% template bool AbsGeq<%Float%>(const %Float% &%x%, const %Float% &%y%) %$$ in the $code CppAD$$ namespace. This function returns true if the absolute value of $icode x$$ is greater than or equal the absolute value of $icode y$$. It is used by $code LuFactor$$ to choose the pivot elements. This template function definition uses the operator $code <=$$ to obtain the absolute value for $icode Float$$ objects. If this operator is not defined for your use of $icode Float$$, you will need to specialize this template so that it works for your use of $code LuFactor$$. $pre $$ Complex numbers do not have the operation $code <=$$ defined. The specializations $codei% bool AbsGeq< std::complex > (const std::complex &%x%, const std::complex &%y%) bool AbsGeq< std::complex > (const std::complex &%x%, const std::complex &%y%) %$$ are define by including $code lu_factor.hpp$$ These return true if the sum of the square of the real and imaginary parts of $icode x$$ is greater than or equal the sum of the square of the real and imaginary parts of $icode y$$. $children% example/lu_factor.cpp% omh/lu_factor_hpp.omh %$$ $head Example$$ The file $cref lu_factor.cpp$$ contains an example and test of using $code LuFactor$$ by itself. It returns true if it succeeds and false otherwise. $pre $$ The file $cref lu_solve.hpp$$ provides a useful example usage of $code LuFactor$$ with $code LuInvert$$. $head Source$$ The file $cref lu_factor.hpp$$ contains the current source code that implements these specifications. $end -------------------------------------------------------------------------- */ // BEGIN C++ # include # include # include # include # include namespace CppAD { // BEGIN CppAD namespace // AbsGeq template inline bool AbsGeq(const Float &x, const Float &y) { Float xabs = x; if( xabs <= Float(0) ) xabs = - xabs; Float yabs = y; if( yabs <= Float(0) ) yabs = - yabs; return xabs >= yabs; } inline bool AbsGeq( const std::complex &x, const std::complex &y) { double xsq = x.real() * x.real() + x.imag() * x.imag(); double ysq = y.real() * y.real() + y.imag() * y.imag(); return xsq >= ysq; } inline bool AbsGeq( const std::complex &x, const std::complex &y) { float xsq = x.real() * x.real() + x.imag() * x.imag(); float ysq = y.real() * y.real() + y.imag() * y.imag(); return xsq >= ysq; } // Lines that are different from code in cppad/local/lu_ratio.hpp end with // template // int LuFactor(SizeVector &ip, SizeVector &jp, FloatVector &LU) // { // type of the elements of LU // typedef typename FloatVector::value_type Float; // // check numeric type specifications CheckNumericType(); // check simple vector class specifications CheckSimpleVector(); CheckSimpleVector(); size_t i, j; // some temporary indices const Float zero( 0 ); // the value zero as a Float object size_t imax; // row index of maximum element size_t jmax; // column indx of maximum element Float emax; // maximum absolute value size_t p; // count pivots int sign; // sign of the permutation Float etmp; // temporary element Float pivot; // pivot element // ------------------------------------------------------- size_t n = ip.size(); CPPAD_ASSERT_KNOWN( size_t(jp.size()) == n, "Error in LuFactor: jp must have size equal to n" ); CPPAD_ASSERT_KNOWN( size_t(LU.size()) == n * n, "Error in LuFactor: LU must have size equal to n * m" ); // ------------------------------------------------------- // initialize row and column order in matrix not yet pivoted for(i = 0; i < n; i++) { ip[i] = i; jp[i] = i; } // initialize the sign of the permutation sign = 1; // --------------------------------------------------------- // Reduce the matrix P to L * U using n pivots for(p = 0; p < n; p++) { // determine row and column corresponding to element of // maximum absolute value in remaining part of P imax = jmax = n; emax = zero; for(i = p; i < n; i++) { for(j = p; j < n; j++) { CPPAD_ASSERT_UNKNOWN( (ip[i] < n) & (jp[j] < n) ); etmp = LU[ ip[i] * n + jp[j] ]; // check if maximum absolute value so far if( AbsGeq (etmp, emax) ) { imax = i; jmax = j; emax = etmp; } } } CPPAD_ASSERT_KNOWN( (imax < n) & (jmax < n) , "LuFactor can't determine an element with " "maximum absolute value.\n" "Perhaps original matrix contains not a number or infinity.\n" "Perhaps your specialization of AbsGeq is not correct." ); if( imax != p ) { // switch rows so max absolute element is in row p i = ip[p]; ip[p] = ip[imax]; ip[imax] = i; sign = -sign; } if( jmax != p ) { // switch columns so max absolute element is in column p j = jp[p]; jp[p] = jp[jmax]; jp[jmax] = j; sign = -sign; } // pivot using the max absolute element pivot = LU[ ip[p] * n + jp[p] ]; // check for determinant equal to zero if( pivot == zero ) { // abort the mission return 0; } // Reduce U by the elementary transformations that maps // LU( ip[p], jp[p] ) to one. Only need transform elements // above the diagonal in U and LU( ip[p] , jp[p] ) is // corresponding value below diagonal in L. for(j = p+1; j < n; j++) LU[ ip[p] * n + jp[j] ] /= pivot; // Reduce U by the elementary transformations that maps // LU( ip[i], jp[p] ) to zero. Only need transform elements // above the diagonal in U and LU( ip[i], jp[p] ) is // corresponding value below diagonal in L. for(i = p+1; i < n; i++ ) { etmp = LU[ ip[i] * n + jp[p] ]; for(j = p+1; j < n; j++) { LU[ ip[i] * n + jp[j] ] -= etmp * LU[ ip[p] * n + jp[j] ]; } } } return sign; } } // END CppAD namespace // END C++ # endif TMB/inst/include/cppad/RombergMul.h0000644000176200001440000000005514113627761016617 0ustar liggesusers/* $Id$ */ # include "cppad/romberg_mul.hpp" TMB/inst/include/cppad/configure.hpp.in0000644000176200001440000001266414113627761017503 0ustar liggesusers// $Id:$ # ifndef CPPAD_CONFIGURE_INCLUDED # define CPPAD_CONFIGURE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin configure$$ $spell CppAD $$ $section Preprocessor Definitions Used by CppAD$$ $index configure, symbol$$ $index symbol, configure$$ $head Preprocessor Symbols$$ $index preprocessor, symbol$$ $index symbol, processor$$ All of the preprocessor symbols used by CppAD begin with $code CPPAD_$$ (there are some deprecated symbols that begin with $code CppAD$$). $end */ /*! \file configure.hpp Replacement for config.h so that all preprocessor symbols begin with CPPAD_ */ # if __cplusplus >= 201100 /*! \def CPPAD_HAS_RVALUE C++11: Does compiler cupport rvalues; i.e., values with move semantics */ # define CPPAD_HAS_RVALUE @cppad_has_rvalue@ # endif # if __cplusplus >= 201100 /*! def CPPAD_HAS_NULLPTR C++11: Does compiler support the null-pointer constant nullptr */ # define CPPAD_HAS_NULLPTR @cppad_has_nullptr@ # endif # if __cplusplus >= 201100 /*! \def CPPAD_HAS_CSTDINT_8_TO_64 C++11: Does compiler support the types uint_8, uint_16, uint_32, and uint_64 */ # define CPPAD_HAS_CSTDINT_8_TO_64 @cppad_has_cstdint_8_to_64@ # endif # if __cplusplus >= 201100 /*! \def CPPAD_COMPILER_HAS_ERF C++11: Does compiler support std::erf(double) */ # define CPPAD_COMPILER_HAS_ERF @cppad_compiler_has_erf@ # endif # if __cplusplus >= 201100 /*! \def CPPAD_HAS_HIGH_RESOLUTION_CLOCK C++11: Does compiler support std::chrono::high_resolution_clock */ # define CPPAD_HAS_HIGH_RESOLUTION_CLOCK @cppad_has_high_resolution_clock@ # endif /*! \def CPPAD_PACKAGE_STRING cppad-yyyymmdd as a C string where yyyy is year, mm is month, and dd is day. */ # define CPPAD_PACKAGE_STRING "cppad-@cppad_version@" /*! def CPPAD_HAS_COLPACK Was a colpack_prefix specified on the cmake command line. */ # define CPPAD_HAS_COLPACK @cppad_has_colpack@ /*! def CPPAD_INTERNAL_SPARSE_SET is the internal representation used for sparse vectors of std::set either sparse_set or sparse_list). */ # define CPPAD_INTERNAL_SPARSE_SET @cppad_internal_sparse_set@ /*! \def CPPAD_IMPLICIT_CTOR_FROM_ANY_TYPE If this symbol is one, an implicit constor of AD is defined where the argument has any type. Otherwise this constructor is explicit. */ # define CPPAD_IMPLICIT_CTOR_FROM_ANY_TYPE @cppad_implicit_ctor_from_any_type@ /*! \def CPPAD_BOOSTVECTOR If this symbol is one, and _MSC_VER is not defined, we are using boost vector for CPPAD_TESTVECTOR. It this symbol is zero, we are not using boost vector for CPPAD_TESTVECTOR. */ # define CPPAD_BOOSTVECTOR @cppad_boostvector@ /*! \def CPPAD_CPPADVECTOR If this symbol is one, we are using CppAD vector for CPPAD_TESTVECTOR. It this symbol is zero, we are not using CppAD vector for CPPAD_TESTVECTOR. */ # define CPPAD_CPPADVECTOR @cppad_cppadvector@ /*! \def CPPAD_STDVECTOR If this symbol is one, we are using standard vector for CPPAD_TESTVECTOR. It this symbol is zero, we are not using standard vector for CPPAD_TESTVECTOR. */ # define CPPAD_STDVECTOR @cppad_stdvector@ /*! \def CPPAD_EIGENVECTOR If this symbol is one, we are using Eigen vector for CPPAD_TESTVECTOR. If this symbol is zero, we are not using Eigen vector for CPPAD_TESTVECTOR. */ # define CPPAD_EIGENVECTOR @cppad_eigenvector@ /*! \def CPPAD_HAS_GETTIMEOFDAY If this symbol is one, and _MSC_VER is not defined, this system supports the gettimeofday funcgtion. Otherwise, this smybol should be zero. */ # define CPPAD_HAS_GETTIMEOFDAY @cppad_has_gettimeofday@ /*! \def CPPAD_SIZE_T_NOT_UNSIGNED_INT If this symbol is zero, the type size_t is the same as the type unsigned int, otherwise this symbol is one. */ # define CPPAD_SIZE_T_NOT_UNSIGNED_INT @cppad_size_t_not_unsigned_int@ /*! \def CPPAD_TAPE_ADDR_TYPE Is the type used to store address on the tape. If not size_t, then sizeof(CPPAD_TAPE_ADDR_TYPE) <= sizeof( size_t ) to conserve memory. This type must support \c std::numeric_limits, the \c <= operator, and conversion to \c size_t. Make sure that the type chosen returns true for is_pod in pod_vector.hpp. This type is later defined as \c addr_t in the CppAD namespace. */ # define CPPAD_TAPE_ADDR_TYPE @cppad_tape_addr_type@ /*! \def CPPAD_TAPE_ID_TYPE Is the type used to store tape identifiers. If not size_t, then sizeof(CPPAD_TAPE_ID_TYPE) <= sizeof( size_t ) to conserve memory. This type must support \c std::numeric_limits, the \c <= operator, and conversion to \c size_t. Make sure that the type chosen returns true for is_pod in pod_vector.hpp. This type is later defined as \c tape_id_t in the CppAD namespace. */ # define CPPAD_TAPE_ID_TYPE @cppad_tape_id_type@ /*! \def CPPAD_MAX_NUM_THREADS Specifies the maximum number of threads that CppAD can support (must be greater than or equal four). The user may define CPPAD_MAX_NUM_THREADS before including any of the CppAD header files. If it is not yet defined, */ # ifndef CPPAD_MAX_NUM_THREADS # define CPPAD_MAX_NUM_THREADS @cppad_max_num_threads@ # endif # endif TMB/inst/include/cppad/ode_gear.hpp0000644000176200001440000003072314536067012016652 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ODE_GEAR_INCLUDED # define CPPAD_ODE_GEAR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin OdeGear$$ $spell cppad.hpp Jan bool const CppAD dep $$ $index OdeGear$$ $index Ode, Gear$$ $index Gear, Ode$$ $index stiff, Ode$$ $index differential, equation$$ $index equation, differential$$ $section An Arbitrary Order Gear Method$$ $head Syntax$$ $codei%# include %$$ $codei%OdeGear(%F%, %m%, %n%, %T%, %X%, %e%)%$$ $head Purpose$$ This routine applies $cref/Gear's Method/OdeGear/Gear's Method/$$ to solve an explicit set of ordinary differential equations. We are given $latex f : \B{R} \times \B{R}^n \rightarrow \B{R}^n$$ be a smooth function. This routine solves the following initial value problem $latex \[ \begin{array}{rcl} x( t_{m-1} ) & = & x^0 \\ x^\prime (t) & = & f[t , x(t)] \end{array} \] $$ for the value of $latex x( t_m )$$. If your set of ordinary differential equations are not stiff an explicit method may be better (perhaps $cref Runge45$$.) $head Include$$ The file $code cppad/ode_gear.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Fun$$ The class $icode Fun$$ and the object $icode F$$ satisfy the prototype $codei% %Fun% &%F% %$$ This must support the following set of calls $codei% %F%.Ode(%t%, %x%, %f%) %F%.Ode_dep(%t%, %x%, %f_x%) %$$ $subhead t$$ The argument $icode t$$ has prototype $codei% const %Scalar% &%t% %$$ (see description of $cref/Scalar/OdeGear/Scalar/$$ below). $subhead x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ and has size $icode n$$ (see description of $cref/Vector/OdeGear/Vector/$$ below). $subhead f$$ The argument $icode f$$ to $icode%F%.Ode%$$ has prototype $codei% %Vector% &%f% %$$ On input and output, $icode f$$ is a vector of size $icode n$$ and the input values of the elements of $icode f$$ do not matter. On output, $icode f$$ is set equal to $latex f(t, x)$$ (see $icode f(t, x)$$ in $cref/Purpose/OdeGear/Purpose/$$). $subhead f_x$$ The argument $icode f_x$$ has prototype $codei% %Vector% &%f_x% %$$ On input and output, $icode f_x$$ is a vector of size $latex n * n$$ and the input values of the elements of $icode f_x$$ do not matter. On output, $latex \[ f\_x [i * n + j] = \partial_{x(j)} f_i ( t , x ) \] $$ $subhead Warning$$ The arguments $icode f$$, and $icode f_x$$ must have a call by reference in their prototypes; i.e., do not forget the $code &$$ in the prototype for $icode f$$ and $icode f_x$$. $head m$$ The argument $icode m$$ has prototype $codei% size_t %m% %$$ It specifies the order (highest power of $latex t$$) used to represent the function $latex x(t)$$ in the multi-step method. Upon return from $code OdeGear$$, the $th i$$ component of the polynomial is defined by $latex \[ p_i ( t_j ) = X[ j * n + i ] \] $$ for $latex j = 0 , \ldots , m$$ (where $latex 0 \leq i < n$$). The value of $latex m$$ must be greater than or equal one. $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ It specifies the range space dimension of the vector valued function $latex x(t)$$. $head T$$ The argument $icode T$$ has prototype $codei% const %Vector% &%T% %$$ and size greater than or equal to $latex m+1$$. For $latex j = 0 , \ldots m$$, $latex T[j]$$ is the time corresponding to time corresponding to a previous point in the multi-step method. The value $latex T[m]$$ is the time of the next point in the multi-step method. The array $latex T$$ must be monotone increasing; i.e., $latex T[j] < T[j+1]$$. Above and below we often use the shorthand $latex t_j$$ for $latex T[j]$$. $head X$$ The argument $icode X$$ has the prototype $codei% %Vector% &%X% %$$ and size greater than or equal to $latex (m+1) * n$$. On input to $code OdeGear$$, for $latex j = 0 , \ldots , m-1$$, and $latex i = 0 , \ldots , n-1$$ $latex \[ X[ j * n + i ] = x_i ( t_j ) \] $$ Upon return from $code OdeGear$$, for $latex i = 0 , \ldots , n-1$$ $latex \[ X[ m * n + i ] \approx x_i ( t_m ) \] $$ $head e$$ The vector $icode e$$ is an approximate error bound for the result; i.e., $latex \[ e[i] \geq | X[ m * n + i ] - x_i ( t_m ) | \] $$ The order of this approximation is one less than the order of the solution; i.e., $latex \[ e = O ( h^m ) \] $$ where $latex h$$ is the maximum of $latex t_{j+1} - t_j$$. $head Scalar$$ The type $icode Scalar$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, the following operations must be defined for $icode Scalar$$ objects $icode a$$ and $icode b$$: $table $bold Operation$$ $cnext $bold Description$$ $rnext $icode%a% < %b%$$ $cnext less than operator (returns a $code bool$$ object) $tend $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type Scalar/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Example$$ $children% example/ode_gear.cpp %$$ The file $cref ode_gear.cpp$$ contains an example and test a test of using this routine. It returns true if it succeeds and false otherwise. $head Source Code$$ The source code for this routine is in the file $code cppad/ode_gear.hpp$$. $head Theory$$ For this discussion we use the shorthand $latex x_j$$ for the value $latex x ( t_j ) \in \B{R}^n$$ which is not to be confused with $latex x_i (t) \in \B{R}$$ in the notation above. The interpolating polynomial $latex p(t)$$ is given by $latex \[ p(t) = \sum_{j=0}^m x_j \frac{ \prod_{i \neq j} ( t - t_i ) }{ \prod_{i \neq j} ( t_j - t_i ) } \] $$ The derivative $latex p^\prime (t)$$ is given by $latex \[ p^\prime (t) = \sum_{j=0}^m x_j \frac{ \sum_{i \neq j} \prod_{k \neq i,j} ( t - t_k ) }{ \prod_{k \neq j} ( t_j - t_k ) } \] $$ Evaluating the derivative at the point $latex t_\ell$$ we have $latex \[ \begin{array}{rcl} p^\prime ( t_\ell ) & = & x_\ell \frac{ \sum_{i \neq \ell} \prod_{k \neq i,\ell} ( t_\ell - t_k ) }{ \prod_{k \neq \ell} ( t_\ell - t_k ) } + \sum_{j \neq \ell} x_j \frac{ \sum_{i \neq j} \prod_{k \neq i,j} ( t_\ell - t_k ) }{ \prod_{k \neq j} ( t_j - t_k ) } \\ & = & x_\ell \sum_{i \neq \ell} \frac{ 1 }{ t_\ell - t_i } + \sum_{j \neq \ell} x_j \frac{ \prod_{k \neq \ell,j} ( t_\ell - t_k ) }{ \prod_{k \neq j} ( t_j - t_k ) } \\ & = & x_\ell \sum_{k \neq \ell} ( t_\ell - t_k )^{-1} + \sum_{j \neq \ell} x_j ( t_j - t_\ell )^{-1} \prod_{k \neq \ell ,j} ( t_\ell - t_k ) / ( t_j - t_k ) \end{array} \] $$ We define the vector $latex \alpha \in \B{R}^{m+1}$$ by $latex \[ \alpha_j = \left\{ \begin{array}{ll} \sum_{k \neq m} ( t_m - t_k )^{-1} & {\rm if} \; j = m \\ ( t_j - t_m )^{-1} \prod_{k \neq m,j} ( t_m - t_k ) / ( t_j - t_k ) & {\rm otherwise} \end{array} \right. \] $$ It follows that $latex \[ p^\prime ( t_m ) = \alpha_0 x_0 + \cdots + \alpha_m x_m \] $$ Gear's method determines $latex x_m$$ by solving the following nonlinear equation $latex \[ f( t_m , x_m ) = \alpha_0 x_0 + \cdots + \alpha_m x_m \] $$ Newton's method for solving this equation determines iterates, which we denote by $latex x_m^k$$, by solving the following affine approximation of the equation above $latex \[ \begin{array}{rcl} f( t_m , x_m^{k-1} ) + \partial_x f( t_m , x_m^{k-1} ) ( x_m^k - x_m^{k-1} ) & = & \alpha_0 x_0^k + \alpha_1 x_1 + \cdots + \alpha_m x_m \\ \left[ \alpha_m I - \partial_x f( t_m , x_m^{k-1} ) \right] x_m & = & \left[ f( t_m , x_m^{k-1} ) - \partial_x f( t_m , x_m^{k-1} ) x_m^{k-1} - \alpha_0 x_0 - \cdots - \alpha_{m-1} x_{m-1} \right] \end{array} \] $$ In order to initialize Newton's method; i.e. choose $latex x_m^0$$ we define the vector $latex \beta \in \B{R}^{m+1}$$ by $latex \[ \beta_j = \left\{ \begin{array}{ll} \sum_{k \neq m-1} ( t_{m-1} - t_k )^{-1} & {\rm if} \; j = m-1 \\ ( t_j - t_{m-1} )^{-1} \prod_{k \neq m-1,j} ( t_{m-1} - t_k ) / ( t_j - t_k ) & {\rm otherwise} \end{array} \right. \] $$ It follows that $latex \[ p^\prime ( t_{m-1} ) = \beta_0 x_0 + \cdots + \beta_m x_m \] $$ We solve the following approximation of the equation above to determine $latex x_m^0$$: $latex \[ f( t_{m-1} , x_{m-1} ) = \beta_0 x_0 + \cdots + \beta_{m-1} x_{m-1} + \beta_m x_m^0 \] $$ $head Gear's Method$$ C. W. Gear, ``Simultaneous Numerical Solution of Differential-Algebraic Equations,'' IEEE Transactions on Circuit Theory, vol. 18, no. 1, pp. 89-95, Jan. 1971. $end -------------------------------------------------------------------------- */ # include # include # include # include # include # include # include namespace CppAD { // BEGIN CppAD namespace template void OdeGear( Fun &F , size_t m , size_t n , const Vector &T , Vector &X , Vector &e ) { // temporary indices size_t i, j, k; typedef typename Vector::value_type Scalar; // check numeric type specifications CheckNumericType(); // check simple vector class specifications CheckSimpleVector(); CPPAD_ASSERT_KNOWN( m >= 1, "OdeGear: m is less than one" ); CPPAD_ASSERT_KNOWN( n > 0, "OdeGear: n is equal to zero" ); CPPAD_ASSERT_KNOWN( size_t(T.size()) >= (m+1), "OdeGear: size of T is not greater than or equal (m+1)" ); CPPAD_ASSERT_KNOWN( size_t(X.size()) >= (m+1) * n, "OdeGear: size of X is not greater than or equal (m+1) * n" ); for(j = 0; j < m; j++) CPPAD_ASSERT_KNOWN( T[j] < T[j+1], "OdeGear: the array T is not monotone increasing" ); // some constants Scalar zero(0); Scalar one(1); // vectors required by method Vector alpha(m + 1); Vector beta(m + 1); Vector f(n); Vector f_x(n * n); Vector x_m0(n); Vector x_m(n); Vector b(n); Vector A(n * n); // compute alpha[m] alpha[m] = zero; for(k = 0; k < m; k++) alpha[m] += one / (T[m] - T[k]); // compute beta[m-1] beta[m-1] = one / (T[m-1] - T[m]); for(k = 0; k < m-1; k++) beta[m-1] += one / (T[m-1] - T[k]); // compute other components of alpha for(j = 0; j < m; j++) { // compute alpha[j] alpha[j] = one / (T[j] - T[m]); for(k = 0; k < m; k++) { if( k != j ) { alpha[j] *= (T[m] - T[k]); alpha[j] /= (T[j] - T[k]); } } } // compute other components of beta for(j = 0; j <= m; j++) { if( j != m-1 ) { // compute beta[j] beta[j] = one / (T[j] - T[m-1]); for(k = 0; k <= m; k++) { if( k != j && k != m-1 ) { beta[j] *= (T[m-1] - T[k]); beta[j] /= (T[j] - T[k]); } } } } // evaluate f(T[m-1], x_{m-1} ) for(i = 0; i < n; i++) x_m[i] = X[(m-1) * n + i]; F.Ode(T[m-1], x_m, f); // solve for x_m^0 for(i = 0; i < n; i++) { x_m[i] = f[i]; for(j = 0; j < m; j++) x_m[i] -= beta[j] * X[j * n + i]; x_m[i] /= beta[m]; } x_m0 = x_m; // evaluate partial w.r.t x of f(T[m], x_m^0) F.Ode_dep(T[m], x_m, f_x); // compute the matrix A = ( alpha[m] * I - f_x ) for(i = 0; i < n; i++) { for(j = 0; j < n; j++) A[i * n + j] = - f_x[i * n + j]; A[i * n + i] += alpha[m]; } // LU factor (and overwrite) the matrix A int sign; CPPAD_UNUSED(sign); CppAD::vector ip(n) , jp(n); sign = LuFactor(ip, jp, A); CPPAD_ASSERT_KNOWN( sign != 0, "OdeGear: step size is to large" ); // Iterations of Newton's method for(k = 0; k < 3; k++) { // only evaluate f( T[m] , x_m ) keep f_x during iteration F.Ode(T[m], x_m, f); // b = f + f_x x_m - alpha[0] x_0 - ... - alpha[m-1] x_{m-1} for(i = 0; i < n; i++) { b[i] = f[i]; for(j = 0; j < n; j++) b[i] -= f_x[i * n + j] * x_m[j]; for(j = 0; j < m; j++) b[i] -= alpha[j] * X[ j * n + i ]; } LuInvert(ip, jp, A, b); x_m = b; } // return estimate for x( t[k] ) and the estimated error bound for(i = 0; i < n; i++) { X[m * n + i] = x_m[i]; e[i] = x_m[i] - x_m0[i]; if( e[i] < zero ) e[i] = - e[i]; } } } // End CppAD namespace # endif TMB/inst/include/cppad/Runge45.h0000644000176200001440000000005214113627761015772 0ustar liggesusers/* $Id$ */ # include "cppad/runge_45.hpp" TMB/inst/include/cppad/poly.hpp0000644000176200001440000001140014536067013016060 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_POLY_INCLUDED # define CPPAD_POLY_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Poly$$ $spell cppad.hpp CppAD namespace cstddef ifndef endif deg const std da $$ $index Poly$$ $index polynomial$$ $index derivative, polynomial template$$ $index template, polynomial derivative$$ $section Evaluate a Polynomial or its Derivative$$ $head Syntax$$ $code # include $$ $pre $$ $icode%p% = Poly(%k%, %a%, %z%)%$$ $head Description$$ Computes the $th k$$ derivative of the polynomial $latex \[ P(z) = a_0 + a_1 z^1 + \cdots + a_d z^d \] $$ If $icode k$$ is equal to zero, the return value is $latex P(z)$$. $head Include$$ The file $code cppad/poly.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. Including this file defines $code Poly$$ within the $code CppAD$$ namespace. $head k$$ The argument $icode k$$ has prototype $codei% size_t %k% %$$ It specifies the order of the derivative to calculate. $head a$$ The argument $icode a$$ has prototype $codei% const %Vector% &%a% %$$ (see $cref/Vector/Poly/Vector/$$ below). It specifies the vector corresponding to the polynomial $latex P(z)$$. $head z$$ The argument $icode z$$ has prototype $codei% const %Type% &%z% %$$ (see $icode Type$$ below). It specifies the point at which to evaluate the polynomial $head p$$ The result $icode p$$ has prototype $codei% %Type% %p% %$$ (see $cref/Type/Poly/Type/$$ below) and it is equal to the $th k$$ derivative of $latex P(z)$$; i.e., $latex \[ p = \frac{k !}{0 !} a_k + \frac{(k+1) !}{1 !} a_{k+1} z^1 + \ldots + \frac{d !}{(d - k) !} a_d z^{d - k} \] $$ If $latex k > d$$, $icode%p% = %Type%(0)%$$. $head Type$$ The type $icode Type$$ is determined by the argument $icode z$$. It is assumed that multiplication and addition of $icode Type$$ objects are commutative. $subhead Operations$$ The following operations must be supported where $icode x$$ and $icode y$$ are objects of type $icode Type$$ and $icode i$$ is an $code int$$: $table $icode%x% = %i%$$ $cnext assignment $rnext $icode%x% = %y%$$ $cnext assignment $rnext $icode%x% *= %y%$$ $cnext multiplication computed assignment $rnext $icode%x% += %y%$$ $cnext addition computed assignment $tend $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Type$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Operation Sequence$$ The $icode Type$$ operation sequence used to calculate $icode p$$ is $cref/independent/glossary/Operation/Independent/$$ of $icode z$$ and the elements of $icode a$$ (it does depend on the size of the vector $icode a$$). $children% example/poly.cpp% omh/poly_hpp.omh %$$ $head Example$$ The file $cref poly.cpp$$ contains an example and test of this routine. It returns true if it succeeds and false otherwise. $head Source$$ The file $cref poly.hpp$$ contains the current source code that implements these specifications. $end ------------------------------------------------------------------------------ */ // BEGIN C++ # include // used to defined size_t # include namespace CppAD { // BEGIN CppAD namespace template Type Poly(size_t k, const Vector &a, const Type &z) { size_t i; size_t d = a.size() - 1; Type tmp; // check Vector is Simple Vector class with Type elements CheckSimpleVector(); // case where derivative order greater than degree of polynomial if( k > d ) { tmp = 0; return tmp; } // case where we are evaluating a derivative if( k > 0 ) { // initialize factor as (k-1) ! size_t factor = 1; for(i = 2; i < k; i++) factor *= i; // set b to coefficient vector corresponding to derivative Vector b(d - k + 1); for(i = k; i <= d; i++) { factor *= i; tmp = factor; b[i - k] = a[i] * tmp; factor /= (i - k + 1); } // value of derivative polynomial return Poly(0, b, z); } // case where we are evaluating the original polynomial Type sum = a[d]; i = d; while(i > 0) { sum *= z; sum += a[--i]; } return sum; } } // END CppAD namespace // END C++ # endif TMB/inst/include/cppad/TrackNewDel.h0000644000176200001440000000005714113627761016711 0ustar liggesusers/* $Id$ */ # include "cppad/track_new_del.hpp" TMB/inst/include/cppad/track_new_del.hpp0000644000176200001440000003377314536067013017717 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_TRACK_NEW_DEL_INCLUDED # define CPPAD_TRACK_NEW_DEL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin TrackNewDel$$ $spell cppad.hpp Cpp newptr Vec oldptr newlen ncopy const $$ $section Routines That Track Use of New and Delete$$ $index new, track$$ $index delete, track$$ $index track, new and delete$$ $index memory, track$$ $head Deprecated 2007-07-23$$ $index deprecated, track memory$$ All these routines have been deprecated. You should use the $cref thread_alloc$$ memory allocator instead (which works better in both a single thread and properly in multi-threading environment). $head Syntax$$ $codei%# include %$$ $icode%newptr% = TrackNewVec(%file%, %line%, %newlen%, %oldptr%) %$$ $codei%TrackDelVec(%file%, %line%, %oldptr%) %$$ $icode%newptr% = TrackExtend(%file%, %line%, %newlen%, %ncopy%, %oldptr%) %$$ $icode%count% = TrackCount(%file%, %line%)%$$ $head Purpose$$ These routines aid in the use of $code new[]$$ and $code delete[]$$ during the execution of a C++ program. $head Include$$ The file $code cppad/track_new_del.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the CppAD include files. $head file$$ The argument $icode file$$ has prototype $codei% const char *%file% %$$ It should be the source code file name where the call to $code TrackNew$$ is located. The best way to accomplish this is the use the preprocessor symbol $code __FILE__$$ for this argument. $head line$$ The argument $icode line$$ has prototype $codei% int %line% %$$ It should be the source code file line number where the call to $code TrackNew$$ is located. The best way to accomplish this is the use the preprocessor symbol $code __LINE__$$ for this argument. $head oldptr$$ The argument $icode oldptr$$ has prototype $codei% %Type% *%oldptr% %$$ This argument is used to identify the type $icode Type$$. $head newlen$$ The argument $icode newlen$$ has prototype $codei% size_t %newlen% %$$ $head head newptr$$ The return value $icode newptr$$ has prototype $codei% %Type% *%newptr% %$$ It points to the newly allocated vector of objects that were allocated using $codei% new Type[%newlen%] %$$ $head ncopy$$ The argument $icode ncopy$$ has prototype $codei% size_t %ncopy% %$$ This specifies the number of elements that are copied from the old array to the new array. The value of $icode ncopy$$ must be less than or equal $icode newlen$$. $head TrackNewVec$$ $index TrackNewVec$$ $index NDEBUG$$ If $code NDEBUG$$ is defined, this routine only sets $codei% %newptr% = %Type% new[%newlen%] %$$ The value of $icode oldptr$$ does not matter (except that it is used to identify $icode Type$$). If $code NDEBUG$$ is not defined, $code TrackNewVec$$ also tracks the this memory allocation. In this case, if memory cannot be allocated $cref ErrorHandler$$ is used to generate a message stating that there was not sufficient memory. $subhead Macro$$ $index CPPAD_TRACK_NEW_VEC$$ The preprocessor macro call $codei% CPPAD_TRACK_NEW_VEC(%newlen%, %oldptr%) %$$ expands to $codei% CppAD::TrackNewVec(__FILE__, __LINE__, %newlen%, %oldptr%) %$$ $subhead Previously Deprecated$$ $index CppADTrackNewVec$$ The preprocessor macro $code CppADTrackNewVec$$ is the same as $code CPPAD_TRACK_NEW_VEC$$ and was previously deprecated. $head TrackDelVec$$ $index TrackDelVec$$ This routine is used to a vector of objects that have been allocated using $code TrackNew$$ or $code TrackExtend$$. If $code NDEBUG$$ is defined, this routine only frees memory with $codei% delete [] %oldptr% %$$ If $code NDEBUG$$ is not defined, $code TrackDelete$$ also checks that $icode oldptr$$ was allocated by $code TrackNew$$ or $code TrackExtend$$ and has not yet been freed. If this is not the case, $cref ErrorHandler$$ is used to generate an error message. $subhead Macro$$ $index CPPAD_TRACK_DEL_VEC$$ The preprocessor macro call $codei% CPPAD_TRACK_DEL_VEC(%oldptr%) %$$ expands to $codei% CppAD::TrackDelVec(__FILE__, __LINE__, %oldptr%) %$$ $subhead Previously Deprecated$$ $index CppADTrackDelVec$$ The preprocessor macro $code CppADTrackDelVec$$ is the same as $code CPPAD_TRACK_DEL_VEC$$ was previously deprecated. $head TrackExtend$$ $index TrackExtend$$ This routine is used to allocate a new vector (using $code TrackNewVec$$), copy $icode ncopy$$ elements from the old vector to the new vector. If $icode ncopy$$ is greater than zero, $icode oldptr$$ must have been allocated using $code TrackNewVec$$ or $code TrackExtend$$. In this case, the vector pointed to by $icode oldptr$$ must be have at least $icode ncopy$$ elements and it will be deleted (using $code TrackDelVec$$). Note that the dependence of $code TrackExtend$$ on $code NDEBUG$$ is indirectly through the routines $code TrackNewVec$$ and $code TrackDelVec$$. $subhead Macro$$ $index CPPAD_TRACK_EXTEND$$ The preprocessor macro call $codei% CPPAD_TRACK_EXTEND(%newlen%, %ncopy%, %oldptr%) %$$ expands to $codei% CppAD::TrackExtend(__FILE__, __LINE__, %newlen%, %ncopy%, %oldptr%) %$$ $subhead Previously Deprecated$$ $index CppADTrackExtend$$ The preprocessor macro $code CppADTrackExtend$$ is the same as $code CPPAD_TRACK_EXTEND$$ and was previously deprecated. $head TrackCount$$ $index TrackCount$$ The return value $icode count$$ has prototype $codei% size_t %count% %$$ If $code NDEBUG$$ is defined, $icode count$$ will be zero. Otherwise, it will be the number of vectors that have been allocated (by $code TrackNewVec$$ or $code TrackExtend$$) and not yet freed (by $code TrackDelete$$). $subhead Macro$$ $index CPPAD_TRACK_COUNT$$ The preprocessor macro call $codei% CPPAD_TRACK_COUNT() %$$ expands to $codei% CppAD::TrackCount(__FILE__, __LINE__) %$$ $subhead Previously Deprecated$$ $index CppADTrackNewVec$$ The preprocessor macro $code CppADTrackCount$$ is the same as $code CPPAD_TRACK_COUNT$$ and was previously deprecated. $head Multi-Threading$$ $index multi-threading, TrackCount$$ $index TrackCount, multi-threading$$ $index thread, multi TrackCount$$ These routines cannot be used $cref/in_parallel/ta_in_parallel/$$ execution mode. Use the $cref thread_alloc$$ routines instead. $head Example$$ $children% test_more/track_new_del.cpp %$$ The file $cref TrackNewDel.cpp$$ contains an example and test of these functions. It returns true, if it succeeds, and false otherwise. $end ------------------------------------------------------------------------------ */ # include # include # include # include # include # ifndef CPPAD_TRACK_DEBUG # define CPPAD_TRACK_DEBUG 0 # endif // ------------------------------------------------------------------------- # define CPPAD_TRACK_NEW_VEC(newlen, oldptr) \ CppAD::TrackNewVec(__FILE__, __LINE__, newlen, oldptr) # define CPPAD_TRACK_DEL_VEC(oldptr) \ CppAD::TrackDelVec(__FILE__, __LINE__, oldptr) # define CPPAD_TRACK_EXTEND(newlen, ncopy, oldptr) \ CppAD::TrackExtend(__FILE__, __LINE__, newlen, ncopy, oldptr) # define CPPAD_TRACK_COUNT() \ CppAD::TrackCount(__FILE__, __LINE__) // ------------------------------------------------------------------------- # define CppADTrackNewVec CPPAD_TRACK_NEW_VEC # define CppADTrackDelVec CPPAD_TRACK_DEL_VEC # define CppADTrackExtend CPPAD_TRACK_EXTEND # define CppADTrackCount CPPAD_TRACK_COUNT // ------------------------------------------------------------------------- namespace CppAD { // Begin CppAD namespace // TrackElement ------------------------------------------------------------ class TrackElement { public: std::string file; // corresponding file name int line; // corresponding line number void *ptr; // value returned by TrackNew TrackElement *next; // next element in linked list // default contructor (used to initialize root) TrackElement(void) : file(""), line(0), ptr(CPPAD_NULL), next(CPPAD_NULL) { } TrackElement(const char *f, int l, void *p) : file(f), line(l), ptr(p), next(CPPAD_NULL) { CPPAD_ASSERT_UNKNOWN( p != CPPAD_NULL); } // There is only one tracking list and it starts it here static TrackElement *Root(void) { CPPAD_ASSERT_UNKNOWN( ! thread_alloc::in_parallel() ); static TrackElement root; return &root; } // Print one tracking element static void Print(TrackElement* E) { CPPAD_ASSERT_UNKNOWN( ! thread_alloc::in_parallel() ); Rcout << "E = " << E; Rcout << ", E->next = " << E->next; Rcout << ", E->ptr = " << E->ptr; Rcout << ", E->line = " << E->line; Rcout << ", E->file = " << E->file; Rcout << std::endl; } // Print the linked list for a thread static void Print(void) { CPPAD_ASSERT_UNKNOWN( ! thread_alloc::in_parallel() ); using std::endl; TrackElement *E = Root(); // convert int(size_t) to avoid warning on _MSC_VER systems Rcout << "Begin Track List" << endl; while( E->next != CPPAD_NULL ) { E = E->next; Print(E); } Rcout << "End Track List:" << endl; Rcout << endl; } }; // TrackError ---------------------------------------------------------------- inline void TrackError( const char *routine, const char *file, int line, const char *msg ) { CPPAD_ASSERT_UNKNOWN( ! thread_alloc::in_parallel() ); std::ostringstream buf; buf << routine << ": at line " << line << " in file " << file << std::endl << msg; std::string str = buf.str(); size_t n = str.size(); size_t i; char *message = new char[n + 1]; for(i = 0; i < n; i++) message[i] = str[i]; message[n] = '\0'; CPPAD_ASSERT_KNOWN( false , message); } // TrackNewVec --------------------------------------------------------------- # ifdef NDEBUG template inline Type *TrackNewVec( const char *file, int line, size_t len, Type * /* oldptr */ ) { # if CPPAD_TRACK_DEBUG static bool first = true; if( first ) { Rcout << "NDEBUG is defined for TrackNewVec" << std::endl; first = false; } # endif return (new Type[len]); } # else template Type *TrackNewVec( const char *file , int line , size_t len , Type * /* oldptr */ ) { CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "attempt to use TrackNewVec in parallel execution mode." ); // try to allocate the new memrory Type *newptr = CPPAD_NULL; try { newptr = new Type[len]; } catch(...) { TrackError("TrackNewVec", file, line, "Cannot allocate sufficient memory" ); } // create tracking element void *vptr = static_cast(newptr); TrackElement *E = new TrackElement(file, line, vptr); // get the root TrackElement *root = TrackElement::Root(); // put this elemenent at the front of linked list E->next = root->next; root->next = E; # if CPPAD_TRACK_DEBUG Rcout << "TrackNewVec: "; TrackElement::Print(E); # endif return newptr; } # endif // TrackDelVec -------------------------------------------------------------- # ifdef NDEBUG template inline void TrackDelVec(const char *file, int line, Type *oldptr) { # if CPPAD_TRACK_DEBUG static bool first = true; if( first ) { Rcout << "NDEBUG is defined in TrackDelVec" << std::endl; first = false; } # endif delete [] oldptr; } # else template void TrackDelVec( const char *file , int line , Type *oldptr ) { CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "attempt to use TrackDelVec in parallel execution mode." ); TrackElement *P; TrackElement *E; // search list for pointer P = TrackElement::Root(); E = P->next; void *vptr = static_cast(oldptr); while(E != CPPAD_NULL && E->ptr != vptr) { P = E; E = E->next; } // check if pointer was not in list if( E == CPPAD_NULL || E->ptr != vptr ) TrackError( "TrackDelVec", file, line, "Invalid value for the argument oldptr.\n" "Possible linking of debug and NDEBUG compliations of CppAD." ); # if CPPAD_TRACK_DEBUG Rcout << "TrackDelVec: "; TrackElement::Print(E); # endif // remove tracking element from list P->next = E->next; // delete allocated pointer delete [] oldptr; // delete tracking element delete E; return; } # endif // TrackExtend -------------------------------------------------------------- template Type *TrackExtend( const char *file , int line , size_t newlen , size_t ncopy , Type *oldptr ) { CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "attempt to use TrackExtend in parallel execution mode." ); # if CPPAD_TRACK_DEBUG Rcout << "TrackExtend: file = " << file; Rcout << ", line = " << line; Rcout << ", newlen = " << newlen; Rcout << ", ncopy = " << ncopy; Rcout << ", oldptr = " << oldptr; Rcout << std::endl; # endif CPPAD_ASSERT_KNOWN( ncopy <= newlen, "TrackExtend: ncopy is greater than newlen." ); // allocate the new memrory Type *newptr = TrackNewVec(file, line, newlen, oldptr); // copy the data size_t i; for(i = 0; i < ncopy; i++) newptr[i] = oldptr[i]; // delete the old vector if( ncopy > 0 ) TrackDelVec(file, line, oldptr); return newptr; } // TrackCount -------------------------------------------------------------- inline size_t TrackCount(const char *file, int line) { CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "attempt to use TrackCount in parallel execution mode." ); size_t count = 0; TrackElement *E = TrackElement::Root(); while( E->next != CPPAD_NULL ) { ++count; E = E->next; } return count; } // --------------------------------------------------------------------------- } // End CppAD namespace // preprocessor symbols local to this file # undef CPPAD_TRACK_DEBUG # endif TMB/inst/include/cppad/ipopt/0000755000176200001440000000000014536067013015523 5ustar liggesusersTMB/inst/include/cppad/ipopt/solve.hpp0000644000176200001440000004114614536067013017372 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SOLVE_INCLUDED # define CPPAD_SOLVE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ipopt_solve$$ $spell Jacobian Jacobians retape Bvector bool infeasibility const cpp cppad doesn't ADvector eval fg gl gu hpp inf ipopt maxiter naninf nf ng nx obj optimizer std xi xl xu zl zu $$ $section Use Ipopt to Solve a Nonlinear Programming Problem$$ $head Syntax$$ $codei%# include %$$ $codei%ipopt::solve( %options%, %xi%, %xl%, %xu%, %gl%, %gu%, %fg_eval%, %solution% )%$$ $head Purpose$$ The function $code ipopt::solve$$ solves nonlinear programming problems of the form $latex \[ \begin{array}{rll} {\rm minimize} & f (x) \\ {\rm subject \; to} & gl \leq g(x) \leq gu \\ & xl \leq x \leq xu \end{array} \] $$ This is done using $href% http://www.coin-or.org/projects/Ipopt.xml% Ipopt %$$ optimizer and CppAD for the derivative and sparsity calculations. $head Include File$$ Currently, this routine $cref/ipopt::solve/ipopt_solve/$$ is not included by the command $codei% # include %$$ (Doing so would require the ipopt library to link the corresponding program (even if $code ipopt::solve$$) was not used.) For this reason, if you are using $code ipopt::solve$$ you should use $codei% # include %$$ which in turn will also include $code $$. $head Bvector$$ The type $icode Bvector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code bool$$. $head Dvector$$ The type $icode DVector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code double$$. $head options$$ The argument $icode options$$ has prototype $codei% const std::string %options% %$$ It contains a list of options. Each option, including the last option, is terminated by the $code '\n'$$ character. Each line consists of two or three tokens separated by one or more spaces. $subhead Retape$$ You can set the retape flag with the following syntax: $codei% Retape %value% %$$ If the value is $code true$$, $code ipopt::solve$$ with retape the $cref/operation sequence/glossary/Operation/Sequence/$$ for each new value of $icode x$$. If the value is $code false$$, $code ipopt::solve$$ will tape the operation sequence at the value of $icode xi$$ and use that sequence for the entire optimization process. The default value is $code false$$. $subhead Sparse$$ You can set the sparse Jacobian and Hessian flag with the following syntax: $codei% Sparse %value% %direction% %$$ If the value is $code true$$, $code ipopt::solve$$ will use a sparse matrix representation for the computation of Jacobians and Hessians. Otherwise, it will use a full matrix representation for these calculations. The default for $icode value$$ is $code false$$. If sparse is true, retape must be false. $pre $$ It is unclear if $cref sparse_jacobian$$ would be faster user forward or reverse mode so you are able to choose the direction. If $codei% %value% == true && %direction% == forward %$$ the Jacobians will be calculated using $code SparseJacobianForward$$. If $codei% %value% == true && %direction% == reverse %$$ the Jacobians will be calculated using $code SparseJacobianReverse$$. $subhead String$$ You can set any Ipopt string option using a line with the following syntax: $codei% String %name% %value% %$$ Here $icode name$$ is any valid Ipopt string option and $icode value$$ is its setting. $subhead Numeric$$ You can set any Ipopt numeric option using a line with the following syntax: $codei% Numeric %name% %value% %$$ Here $icode name$$ is any valid Ipopt numeric option and $icode value$$ is its setting. $subhead Integer$$ You can set any Ipopt integer option using a line with the following syntax: $codei% Integer %name% %value% %$$ Here $icode name$$ is any valid Ipopt integer option and $icode value$$ is its setting. $head xi$$ The argument $icode xi$$ has prototype $codei% const %Vector%& %xi% %$$ and its size is equal to $icode nx$$. It specifies the initial point where Ipopt starts the optimization process. $head xl$$ The argument $icode xl$$ has prototype $codei% const %Vector%& %xl% %$$ and its size is equal to $icode nx$$. It specifies the lower limits for the argument in the optimization problem. $head xu$$ The argument $icode xu$$ has prototype $codei% const %Vector%& %xu% %$$ and its size is equal to $icode nx$$. It specifies the upper limits for the argument in the optimization problem. $head gl$$ The argument $icode gl$$ has prototype $codei% const %Vector%& %gl% %$$ and its size is equal to $icode ng$$. It specifies the lower limits for the constraints in the optimization problem. $head gu$$ The argument $icode gu$$ has prototype $codei% const %Vector%& %gu% %$$ and its size is equal to $icode ng$$. It specifies the upper limits for the constraints in the optimization problem. $head fg_eval$$ The argument $icode fg_eval$$ has prototype $codei% %FG_eval% %fg_eval% %$$ where the class $icode FG_eval$$ is unspecified except for the fact that it supports the syntax $codei% %FG_eval%::ADvector %fg_eval%(%fg%, %x%) %$$ The type $icode ADvector$$ and the arguments to $icode fg$$, $icode x$$ have the following meaning: $subhead ADvector$$ The type $icode%FG_eval%::ADvector%$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code AD$$. $subhead x$$ The $icode fg_eval$$ argument $icode x$$ has prototype $codei% const %ADvector%& %x% %$$ where $icode%nx% = %x%.size()%$$. $subhead fg$$ The $icode fg_eval$$ argument $icode fg$$ has prototype $codei% %ADvector%& %fg% %$$ where $codei%1 + %ng% = %fg%.size()%$$. The input value of the elements of $icode fg$$ does not matter. Upon return from $icode fg_eval$$, $codei% %fg%[0] =%$$ $latex f (x)$$ $codei% %$$ and for $latex i = 0, \ldots , ng-1$$, $codei% %fg%[1 + %i%] =%$$ $latex g_i (x)$$ $head solution$$ The argument $icode solution$$ has prototype $codei% ipopt::solve_result<%Dvector%>& %solution% %$$ After the optimization process is completed, $icode solution$$ contains the following information: $subhead status$$ The $icode status$$ field of $icode solution$$ has prototype $codei% ipopt::solve_result<%Dvector%>::status_type %solution%.status %$$ It is the final Ipopt status for the optimizer. Here is a list of the possible values for the status: $table $icode status$$ $cnext Meaning $rnext not_defined $cnext The optimizer did not return a final status for this problem. $rnext unknown $cnext The status returned by the optimizer is not defined in the Ipopt documentation for $code finalize_solution$$. $rnext success $cnext Algorithm terminated successfully at a point satisfying the convergence tolerances (see Ipopt options). $rnext maxiter_exceeded $cnext The maximum number of iterations was exceeded (see Ipopt options). $rnext stop_at_tiny_step $cnext Algorithm terminated because progress was very slow. $rnext stop_at_acceptable_point $cnext Algorithm stopped at a point that was converged, not to the 'desired' tolerances, but to 'acceptable' tolerances (see Ipopt options). $rnext local_infeasibility $cnext Algorithm converged to a non-feasible point (problem may have no solution). $rnext user_requested_stop $cnext This return value should not happen. $rnext diverging_iterates $cnext It the iterates are diverging. $rnext restoration_failure $cnext Restoration phase failed, algorithm doesn't know how to proceed. $rnext error_in_step_computation $cnext An unrecoverable error occurred while Ipopt tried to compute the search direction. $rnext invalid_number_detected $cnext Algorithm received an invalid number (such as $code nan$$ or $code inf$$) from the users function $icode%fg_info%.eval%$$ or from the CppAD evaluations of its derivatives (see the Ipopt option $code check_derivatives_for_naninf$$). $rnext internal_error $cnext An unknown Ipopt internal error occurred. Contact the Ipopt authors through the mailing list. $tend $subhead x$$ The $code x$$ field of $icode solution$$ has prototype $codei% %Vector% %solution%.x %$$ and its size is equal to $icode nx$$. It is the final $latex x$$ value for the optimizer. $subhead zl$$ The $code zl$$ field of $icode solution$$ has prototype $codei% %Vector% %solution%.zl %$$ and its size is equal to $icode nx$$. It is the final Lagrange multipliers for the lower bounds on $latex x$$. $subhead zu$$ The $code zu$$ field of $icode solution$$ has prototype $codei% %Vector% %solution%.zu %$$ and its size is equal to $icode nx$$. It is the final Lagrange multipliers for the upper bounds on $latex x$$. $subhead g$$ The $code g$$ field of $icode solution$$ has prototype $codei% %Vector% %solution%.g %$$ and its size is equal to $icode ng$$. It is the final value for the constraint function $latex g(x)$$. $subhead lambda$$ The $code lambda$$ field of $icode solution$$ has prototype $codei% %Vector%> %solution%.lambda %$$ and its size is equal to $icode ng$$. It is the final value for the Lagrange multipliers corresponding to the constraint function. $subhead obj_value$$ The $code obj_value$$ field of $icode solution$$ has prototype $codei% double %solution%.obj_value %$$ It is the final value of the objective function $latex f(x)$$. $children% example/ipopt_solve/get_started.cpp% example/ipopt_solve/retape.cpp% example/ipopt_solve/ode_inverse.cpp %$$ $head Example$$ All the examples return true if it succeeds and false otherwise. $subhead get_started$$ The file $cref%example/ipopt_solve/get_started.cpp%ipopt_solve_get_started.cpp%$$ is an example and test of $code ipopt::solve$$ taken from the Ipopt manual. $subhead retape$$ The file $cref%example/ipopt_solve/retape.cpp%ipopt_solve_retape.cpp%$$ demonstrates when it is necessary to specify $cref/retape/ipopt_solve/options/Retape/$$ as true. $subhead ode_inverse$$ The file $cref%example/ipopt_solve/ode_inverse.cpp%ipopt_solve_ode_inverse.cpp%$$ demonstrates using Ipopt to solve for parameters in an ODE model. $end ------------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE namespace ipopt { /*! \file solve.hpp \brief Implement the ipopt::solve Nonlinear Programming Solver */ /*! Use Ipopt to Solve a Nonlinear Programming Problem \tparam Bvector simple vector class with elements of type bool. \tparam Dvector simple vector class with elements of type double. \tparam FG_eval function object used to evaluate f(x) and g(x); see fg_eval below. It must also support \code FG_eval::ADvector \endcode to dentify the type used for the arguments to fg_eval. \param options list of options, one for each line. Ipopt options (are optional) and have one of the following forms \code String name value Numeric name value Integer name value \endcode The following other possible options are listed below: \code Retape value \endcode \param xi initial argument value to start optimization procedure at. \param xl lower limit for argument during optimization \param xu upper limit for argument during optimization \param gl lower limit for g(x) during optimization. \param gu upper limit for g(x) during optimization. \param fg_eval function that evaluates the objective and constraints using the syntax \code fg_eval(fg, x) \endcode \param solution structure that holds the solution of the optimization. */ template void solve( const std::string& options , const Dvector& xi , const Dvector& xl , const Dvector& xu , const Dvector& gl , const Dvector& gu , FG_eval& fg_eval , ipopt::solve_result& solution ) { bool ok = true; typedef typename FG_eval::ADvector ADvector; CPPAD_ASSERT_KNOWN( xi.size() == xl.size() && xi.size() == xu.size() , "ipopt::solve: size of xi, xl, and xu are not all equal." ); CPPAD_ASSERT_KNOWN( gl.size() == gu.size() , "ipopt::solve: size of gl and gu are not equal." ); size_t nx = xi.size(); size_t ng = gl.size(); // Create an IpoptApplication using Ipopt::IpoptApplication; Ipopt::SmartPtr app = new IpoptApplication(); // process the options argument size_t begin_1, end_1, begin_2, end_2, begin_3, end_3; begin_1 = 0; bool retape = false; bool sparse_forward = false; bool sparse_reverse = false; while( begin_1 < options.size() ) { // split this line into tokens while( options[begin_1] == ' ') begin_1++; end_1 = options.find_first_of(" \n", begin_1); begin_2 = end_1; while( options[begin_2] == ' ') begin_2++; end_2 = options.find_first_of(" \n", begin_2); begin_3 = end_2; while( options[begin_3] == ' ') begin_3++; end_3 = options.find_first_of(" \n", begin_3); // check for errors CPPAD_ASSERT_KNOWN( (end_1 != std::string::npos) & (end_2 != std::string::npos) & (end_3 != std::string::npos) , "ipopt::solve: missing '\\n' at end of an option line" ); CPPAD_ASSERT_KNOWN( (end_1 > begin_1) & (end_2 > begin_2) , "ipopt::solve: an option line does not have two tokens" ); // get first two tokens std::string tok_1 = options.substr(begin_1, end_1 - begin_1); std::string tok_2 = options.substr(begin_2, end_2 - begin_2); // get third token std::string tok_3; bool three_tok = false; three_tok |= tok_1 == "Sparse"; three_tok |= tok_1 == "String"; three_tok |= tok_1 == "Numeric"; three_tok |= tok_1 == "Integer"; if( three_tok ) { CPPAD_ASSERT_KNOWN( (end_3 > begin_3) , "ipopt::solve: a Sparse, String, Numeric, or Integer\n" "option line does not have three tokens." ); tok_3 = options.substr(begin_3, end_3 - begin_3); } // switch on option type if( tok_1 == "Retape" ) { CPPAD_ASSERT_KNOWN( (tok_2 == "true") | (tok_2 == "false") , "ipopt::solve: Retape value is not true or false" ); retape = (tok_2 == "true"); } else if( tok_1 == "Sparse" ) { CPPAD_ASSERT_KNOWN( (tok_2 == "true") | (tok_2 == "false") , "ipopt::solve: Sparse value is not true or false" ); CPPAD_ASSERT_KNOWN( (tok_3 == "forward") | (tok_3 == "reverse") , "ipopt::solve: Sparse direction is not forward or reverse" ); if( tok_2 == "false" ) { sparse_forward = false; sparse_reverse = false; } else { sparse_forward = tok_3 == "forward"; sparse_reverse = tok_3 == "reverse"; } } else if ( tok_1 == "String" ) app->Options()->SetStringValue(tok_2.c_str(), tok_3.c_str()); else if ( tok_1 == "Numeric" ) { Ipopt::Number value = std::atof( tok_3.c_str() ); app->Options()->SetNumericValue(tok_2.c_str(), value); } else if ( tok_1 == "Integer" ) { Ipopt::Index value = std::atoi( tok_3.c_str() ); app->Options()->SetIntegerValue(tok_2.c_str(), value); } else CPPAD_ASSERT_KNOWN( false, "ipopt::solve: First token is not one of\n" "Retape, Sparse, String, Numeric, Integer" ); begin_1 = end_3; while( options[begin_1] == ' ') begin_1++; if( options[begin_1] != '\n' ) CPPAD_ASSERT_KNOWN( false, "ipopt::solve: either more than three tokens " "or no '\\n' at end of a line" ); begin_1++; } CPPAD_ASSERT_KNOWN( ! ( retape & (sparse_forward | sparse_reverse) ) , "ipopt::solve: retape and sparse both true is not supported." ); // Initialize the IpoptApplication and process the options Ipopt::ApplicationReturnStatus status = app->Initialize(); ok &= status == Ipopt::Solve_Succeeded; if( ! ok ) { solution.status = solve_result::unknown; return; } // Create an interface from Ipopt to this specific problem. // Note the assumption here that ADvector is same as cppd_ipopt::ADvector size_t nf = 1; Ipopt::SmartPtr cppad_nlp = new CppAD::ipopt::solve_callback( nf, nx, ng, xi, xl, xu, gl, gu, fg_eval, retape, sparse_forward, sparse_reverse, solution ); // Run the IpoptApplication app->OptimizeTNLP(cppad_nlp); return; } } // end ipopt namespace } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/ipopt/solve_callback.hpp0000644000176200001440000007627514536067013021221 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SOLVE_CALLBACK_INCLUDED # define CPPAD_SOLVE_CALLBACK_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE namespace ipopt { /*! \file solve_callback.hpp \brief Class that connects ipopt::solve to Ipopt */ /*! Class that Ipopt uses for obtaining information about this problem. \section Evaluation_Methods Evaluation Methods The set of evaluation methods for this class is \verbatim { eval_f, eval_grad_f, eval_g, eval_jac_g, eval_h } \endverbatim Note that the bool return flag for the evaluations methods does not appear in the Ipopt documentation. Looking at the code, it seems to be a flag telling Ipopt to abort when the flag is false. */ template class solve_callback : public Ipopt::TNLP { private: // ------------------------------------------------------------------ // Types used by this class // ------------------------------------------------------------------ /// A Scalar value used by Ipopt typedef Ipopt::Number Number; /// An index value used by Ipopt typedef Ipopt::Index Index; /// Indexing style used in Ipopt sparsity structure typedef Ipopt::TNLP::IndexStyleEnum IndexStyleEnum; // ------------------------------------------------------------------ // Values directly passed in to constuctor // ------------------------------------------------------------------ /// dimension of the range space for f(x). /// The objective is sum_i f_i (x). /// Note that, at this point, there is no advantage having nf_ > 1. const size_t nf_; /// dimension of the domain space for f(x) and g(x) const size_t nx_; /// dimension of the range space for g(x) const size_t ng_; /// initial value for x const Dvector& xi_; /// lower limit for x const Dvector& xl_; /// upper limit for x const Dvector& xu_; /// lower limit for g(x) const Dvector& gl_; /// upper limit for g(x) const Dvector& gu_; /// object that evaluates f(x) and g(x) FG_eval& fg_eval_; /// should operation sequence be retaped for each new x. bool retape_; /// Should sparse methods be used to compute Jacobians and Hessians /// with forward mode used for Jacobian. bool sparse_forward_; /// Should sparse methods be used to compute Jacobians and Hessians /// with reverse mode used for Jacobian. bool sparse_reverse_; /// final results are returned to this structure solve_result& solution_; // ------------------------------------------------------------------ // Values that are initilaized by the constructor // ------------------------------------------------------------------ /// AD function object that evaluates x -> [ f(x) , g(x) ] /// If retape is false, this object is initialzed by constructor /// otherwise it is set by cache_new_x each time it is called. CppAD::ADFun adfun_; /// value of x corresponding to previous new_x Dvector x0_; /// value of fg corresponding to previous new_x Dvector fg0_; // ---------------------------------------------------------------------- // Jacobian information // ---------------------------------------------------------------------- /// Sparsity pattern for Jacobian of [f(x), g(x) ]. /// If sparse is true, this pattern set by constructor and does not change. /// Otherwise this vector has size zero. CppAD::vector< std::set > pattern_jac_; /// Row indices of [f(x), g(x)] for Jacobian of g(x) in row order. /// (Set by constructor and not changed.) CppAD::vector row_jac_; /// Column indices for Jacobian of g(x), same order as row_jac_. /// (Set by constructor and not changed.) CppAD::vector col_jac_; /// col_order_jac_ sorts row_jac_ and col_jac_ in column order. /// (Set by constructor and not changed.) CppAD::vector col_order_jac_; /// Work vector used by SparseJacobian, stored here to avoid recalculation. CppAD::sparse_jacobian_work work_jac_; // ---------------------------------------------------------------------- // Hessian information // ---------------------------------------------------------------------- /// Sparsity pattern for Hessian of Lagragian /// \f[ L(x) = \sigma \sum_i f_i (x) + \sum_i \lambda_i g_i (x) \f] /// If sparse is true, this pattern set by constructor and does not change. /// Otherwise this vector has size zero. CppAD::vector< std::set > pattern_hes_; /// Row indices of Hessian lower left triangle in row order. /// (Set by constructor and not changed.) CppAD::vector row_hes_; /// Column indices of Hessian left triangle in same order as row_hes_. /// (Set by constructor and not changed.) CppAD::vector col_hes_; /// Work vector used by SparseJacobian, stored here to avoid recalculation. CppAD::sparse_hessian_work work_hes_; // ------------------------------------------------------------------ // Private member functions // ------------------------------------------------------------------ /*! Cache information for a new value of x. \param x is the new value for x. \par x0_ the elements of this vector are set to the new value for x. \par fg0_ the elements of this vector are set to the new value for [f(x), g(x)] \par adfun_ If retape is true, the operation sequence for this function is changes to correspond to the argument x. If retape is false, the operation sequence is not changed. The zero order Taylor coefficients for this function are set so they correspond to the argument x. */ void cache_new_x(const Number* x) { size_t i; if( retape_ ) { // make adfun_, as well as x0_ and fg0_ correspond to this x ADvector a_x(nx_), a_fg(nf_ + ng_); for(i = 0; i < nx_; i++) { x0_[i] = x[i]; a_x[i] = x[i]; } CppAD::Independent(a_x); fg_eval_(a_fg, a_x); adfun_.Dependent(a_x, a_fg); } else { // make x0_ and fg0_ correspond to this x for(i = 0; i < nx_; i++) x0_[i] = x[i]; } fg0_ = adfun_.Forward(0, x0_); } public: // ---------------------------------------------------------------------- /*! Constructor for the interface between ipopt::solve and Ipopt \param nf dimension of the range space for f(x) \param nx dimension of the domain space for f(x) and g(x). \param ng dimension of the range space for g(x) \param xi initial value of x during the optimization procedure (size nx). \param xl lower limit for x (size nx). \param xu upper limit for x (size nx). \param gl lower limit for g(x) (size ng). \param gu upper limit for g(x) (size ng). \param fg_eval function object that evaluations f(x) and g(x) using fg_eval(fg, x) \param retape should the operation sequence be retaped for each argument value. \param sparse_forward should sparse matrix computations be used for Jacobians and Hessians with forward mode for Jacobian. \param sparse_reverse should sparse matrix computations be used for Jacobians and Hessians with reverse mode for Jacobian. (sparse_forward and sparse_reverse cannot both be true). \param solution object where final results are stored. */ solve_callback( size_t nf , size_t nx , size_t ng , const Dvector& xi , const Dvector& xl , const Dvector& xu , const Dvector& gl , const Dvector& gu , FG_eval& fg_eval , bool retape , bool sparse_forward , bool sparse_reverse , solve_result& solution ) : nf_ ( nf ), nx_ ( nx ), ng_ ( ng ), xi_ ( xi ), xl_ ( xl ), xu_ ( xu ), gl_ ( gl ), gu_ ( gu ), fg_eval_ ( fg_eval ), retape_ ( retape ), sparse_forward_ ( sparse_forward ), sparse_reverse_ ( sparse_reverse ), solution_ ( solution ) { CPPAD_ASSERT_UNKNOWN( ! ( sparse_forward_ & sparse_reverse_ ) ); size_t i, j; size_t nfg = nf_ + ng_; // initialize x0_ and fg0_ wih proper dimensions and value nan x0_.resize(nx); fg0_.resize(nfg); for(i = 0; i < nx_; i++) x0_[i] = CppAD::nan(0.0); for(i = 0; i < nfg; i++) fg0_[i] = CppAD::nan(0.0); if( ! retape_ ) { // make adfun_ correspond to x -> [ f(x), g(x) ] ADvector a_x(nx_), a_fg(nfg); for(i = 0; i < nx_; i++) a_x[i] = xi_[i]; CppAD::Independent(a_x); fg_eval_(a_fg, a_x); adfun_.Dependent(a_x, a_fg); // optimize because we will make repeated use of this tape adfun_.optimize(); } if( sparse_forward_ | sparse_reverse_ ) { CPPAD_ASSERT_UNKNOWN( ! retape ); // ----------------------------------------------------------- // Jacobian pattern_jac_.resize(nf_ + ng_); if( nx_ <= nf_ + ng_ ) { // use forward mode to compute sparsity CppAD::vector< std::set > r(nx_); for(i = 0; i < nx_; i++) { CPPAD_ASSERT_UNKNOWN( r[i].empty() ); r[i].insert(i); } pattern_jac_ = adfun_.ForSparseJac(nx_, r); } else { // use reverse mode to compute sparsity size_t m = nf_ + ng_; CppAD::vector< std::set > s(m); for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( s[i].empty() ); s[i].insert(i); } pattern_jac_ = adfun_.RevSparseJac(m, s); } // Set row and column indices in Jacoian of [f(x), g(x)] // for Jacobian of g(x). These indices are in row major order. std::set:: const_iterator itr, end; for(i = nf_; i < nfg; i++) { itr = pattern_jac_[i].begin(); end = pattern_jac_[i].end(); while( itr != end ) { j = *itr++; row_jac_.push_back(i); col_jac_.push_back(j); } } // ----------------------------------------------------------- // Hessian pattern_hes_.resize(nx_); CppAD::vector< std::set > r(nx_); for(i = 0; i < nx_; i++) { CPPAD_ASSERT_UNKNOWN( r[i].empty() ); r[i].insert(i); } // forward Jacobian sparsity for fg adfun_.ForSparseJac(nx_, r); // The Lagragian can use any of the components of f(x), g(x) CppAD::vector< std::set > s(1); CPPAD_ASSERT_UNKNOWN( s[0].empty() ); for(i = 0; i < nf_ + ng_; i++) s[0].insert(i); pattern_hes_ = adfun_.RevSparseHes(nx_, s); // Set row and column indices for Lower triangle of Hessian // of Lagragian. These indices are in row major order. for(i = 0; i < nx_; i++) { itr = pattern_hes_[i].begin(); end = pattern_hes_[i].end(); while( itr != end ) { j = *itr++; if( j <= i ) { row_hes_.push_back(i); col_hes_.push_back(j); } } } } else { // Set row and column indices in Jacoian of [f(x), g(x)] // for Jacobian of g(x). These indices are in row major order. for(i = nf_; i < nfg; i++) { for(j = 0; j < nx_; j++) { row_jac_.push_back(i); col_jac_.push_back(j); } } // Set row and column indices for lower triangle of Hessian. // These indices are in row major order. for(i = 0; i < nx_; i++) { for(j = 0; j <= i; j++) { row_hes_.push_back(i); col_hes_.push_back(j); } } } // Column order indirect sort of the Jacobian indices col_order_jac_.resize( col_jac_.size() ); index_sort( col_jac_, col_order_jac_ ); } // ----------------------------------------------------------------------- /*! Return dimension information about optimization problem. \param[out] n is set to the value nx_. \param[out] m is set to the value ng_. \param[out] nnz_jac_g is set to ng_ * nx_ (sparsity not yet implemented) \param[out] nnz_h_lag is set to nx_*(nx_+1)/2 (sparsity not yet implemented) \param[out] index_style is set to C_STYLE; i.e., zeoro based indexing is used in the information passed to Ipopt. */ virtual bool get_nlp_info( Index& n , Index& m , Index& nnz_jac_g , Index& nnz_h_lag , IndexStyleEnum& index_style ) { n = static_cast(nx_); m = static_cast(ng_); nnz_jac_g = static_cast(row_jac_.size()); nnz_h_lag = static_cast(row_hes_.size()); # ifndef NDEBUG if( ! (sparse_forward_ | sparse_reverse_) ) { size_t nnz = static_cast(nnz_jac_g); CPPAD_ASSERT_UNKNOWN( nnz == ng_ * nx_); // nnz = static_cast(nnz_h_lag); CPPAD_ASSERT_UNKNOWN( nnz == (nx_ * (nx_ + 1)) / 2 ); } # endif // use the fortran index style for row/col entries index_style = C_STYLE; return true; } // ----------------------------------------------------------------------- /*! Return bound information about optimization problem. \param[in] n is the dimension of the domain space for f(x) and g(x); i.e., it must be equal to nx_. \param[out] x_l is a vector of size nx_. The input value of its elements does not matter. On output, it is a copy of the lower bound for \f$ x \f$; i.e., xl_. \param[out] x_u is a vector of size nx_. The input value of its elements does not matter. On output, it is a copy of the upper bound for \f$ x \f$; i.e., xu_. \param[in] m is the dimension of the range space for g(x). i.e., it must be equal to ng_. \param[out] g_l is a vector of size ng_. The input value of its elements does not matter. On output, it is a copy of the lower bound for \f$ g(x) \f$; i.e., gl_. \param[out] g_u is a vector of size ng_. The input value of its elements does not matter. On output, it is a copy of the upper bound for \f$ g(x) \f$; i.e, gu_. */ virtual bool get_bounds_info( Index n , Number* x_l , Number* x_u , Index m , Number* g_l , Number* g_u ) { size_t i; // here, the n and m we gave IPOPT in get_nlp_info are passed back CPPAD_ASSERT_UNKNOWN(static_cast(n) == nx_); CPPAD_ASSERT_UNKNOWN(static_cast(m) == ng_); // pass back bounds for(i = 0; i < nx_; i++) { x_l[i] = xl_[i]; x_u[i] = xu_[i]; } for(i = 0; i < ng_; i++) { g_l[i] = gl_[i]; g_u[i] = gu_[i]; } return true; } // ----------------------------------------------------------------------- /*! Return initial x value where optimiation is started. \param[in] n must be equal to the domain dimension for f(x) and g(x); i.e., it must be equal to nx_. \param[in] init_x must be equal to true. \param[out] x is a vector of size nx_. The input value of its elements does not matter. On output, it is a copy of the initial value for \f$ x \f$; i.e. xi_. \param[in] init_z must be equal to false. \param z_L is not used. \param z_U is not used. \param[in] m must be equal to the domain dimension for f(x) and g(x); i.e., it must be equal to ng_. \param init_lambda must be equal to false. \param lambda is not used. */ virtual bool get_starting_point( Index n , bool init_x , Number* x , bool init_z , Number* z_L , Number* z_U , Index m , bool init_lambda , Number* lambda ) { size_t j; CPPAD_ASSERT_UNKNOWN(static_cast(n) == nx_ ); CPPAD_ASSERT_UNKNOWN(static_cast(m) == ng_ ); CPPAD_ASSERT_UNKNOWN(init_x == true); CPPAD_ASSERT_UNKNOWN(init_z == false); CPPAD_ASSERT_UNKNOWN(init_lambda == false); for(j = 0; j < nx_; j++) x[j] = xi_[j]; return true; } // ----------------------------------------------------------------------- /*! Evaluate the objective fucntion f(x). \param[in] n is the dimension of the argument space for f(x); i.e., must be equal nx_. \param[in] x is a vector of size nx_ containing the point at which to evaluate the function sum_i f_i (x). \param[in] new_x is false if the previous call to any one of the \ref Evaluation_Methods used the same value for x. \param[out] obj_value is the value of the objective sum_i f_i (x) at this value of x. \return The return value is always true; see \ref Evaluation_Methods. */ virtual bool eval_f( Index n , const Number* x , bool new_x , Number& obj_value ) { size_t i; if( new_x ) cache_new_x(x); // double sum = 0.0; for(i = 0; i < nf_; i++) sum += fg0_[i]; obj_value = static_cast(sum); return true; } // ----------------------------------------------------------------------- /*! Evaluate the gradient of f(x). \param[in] n is the dimension of the argument space for f(x); i.e., must be equal nx_. \param[in] x has a vector of size nx_ containing the point at which to evaluate the gradient of f(x). \param[in] new_x is false if the previous call to any one of the \ref Evaluation_Methods used the same value for x. \param[out] grad_f is a vector of size nx_. The input value of its elements does not matter. The output value of its elements is the gradient of f(x) at this value of. \return The return value is always true; see \ref Evaluation_Methods. */ virtual bool eval_grad_f( Index n , const Number* x , bool new_x , Number* grad_f ) { size_t i; if( new_x ) cache_new_x(x); // Dvector w(nf_ + ng_), dw(nx_); for(i = 0; i < nf_; i++) w[i] = 1.0; for(i = 0; i < ng_; i++) w[nf_ + i] = 0.0; dw = adfun_.Reverse(1, w); for(i = 0; i < nx_; i++) grad_f[i] = dw[i]; return true; } // ----------------------------------------------------------------------- /*! Evaluate the function g(x). \param[in] n is the dimension of the argument space for g(x); i.e., must be equal nx_. \param[in] x has a vector of size n containing the point at which to evaluate the gradient of g(x). \param[in] new_x is false if the previous call to any one of the \ref Evaluation_Methods used the same value for x. \param[in] m is the dimension of the range space for g(x); i.e., must be equal to ng_. \param[out] g is a vector of size ng_. The input value of its elements does not matter. The output value of its elements is the value of the function g(x) at this value of x. \return The return value is always true; see \ref Evaluation_Methods. */ virtual bool eval_g( Index n , const Number* x , bool new_x , Index m , Number* g ) { size_t i; if( new_x ) cache_new_x(x); // for(i = 0; i < ng_; i++) g[i] = fg0_[nf_ + i]; return true; } // ----------------------------------------------------------------------- /*! Evaluate the Jacobian of g(x). \param[in] n is the dimension of the argument space for g(x); i.e., must be equal nx_. \param x If values is not NULL, x is a vector of size nx_ containing the point at which to evaluate the gradient of g(x). \param[in] new_x is false if the previous call to any one of the \ref Evaluation_Methods used the same value for x. \param[in] m is the dimension of the range space for g(x); i.e., must be equal to ng_. \param[in] nele_jac is the number of possibly non-zero elements in the Jacobian of g(x); i.e., must be equal to ng_ * nx_. \param iRow if values is not NULL, iRow is not defined. if values is NULL, iRow is a vector with size nele_jac. The input value of its elements does not matter. On output, For k = 0 , ... , nele_jac-1, iRow[k] is the base zero row index for the k-th possibly non-zero entry in the Jacobian of g(x). \param jCol if values is not NULL, jCol is not defined. if values is NULL, jCol is a vector with size nele_jac. The input value of its elements does not matter. On output, For k = 0 , ... , nele_jac-1, jCol[k] is the base zero column index for the k-th possibly non-zero entry in the Jacobian of g(x). \param values if \c values is not \c NULL, \c values is a vector with size \c nele_jac. The input value of its elements does not matter. On output, For k = 0 , ... , nele_jac-1, values[k] is the value for the k-th possibly non-zero entry in the Jacobian of g(x). \return The return value is always true; see \ref Evaluation_Methods. */ virtual bool eval_jac_g( Index n, const Number* x, bool new_x, Index m, Index nele_jac, Index* iRow, Index *jCol, Number* values) { size_t i, j, k, ell; CPPAD_ASSERT_UNKNOWN(static_cast(m) == ng_ ); CPPAD_ASSERT_UNKNOWN(static_cast(n) == nx_ ); // size_t nk = row_jac_.size(); CPPAD_ASSERT_UNKNOWN( static_cast(nele_jac) == nk ); // if( new_x ) cache_new_x(x); if( values == NULL ) { for(k = 0; k < nk; k++) { i = row_jac_[k]; j = col_jac_[k]; CPPAD_ASSERT_UNKNOWN( i >= nf_ ); iRow[k] = static_cast(i - nf_); jCol[k] = static_cast(j); } return true; } // if( nk == 0 ) return true; // if( sparse_forward_ ) { Dvector jac(nk); adfun_.SparseJacobianForward( x0_ , pattern_jac_, row_jac_, col_jac_, jac, work_jac_ ); for(k = 0; k < nk; k++) values[k] = jac[k]; } else if( sparse_reverse_ ) { Dvector jac(nk); adfun_.SparseJacobianReverse( x0_ , pattern_jac_, row_jac_, col_jac_, jac, work_jac_ ); for(k = 0; k < nk; k++) values[k] = jac[k]; } else if( nx_ < ng_ ) { // use forward mode Dvector x1(nx_), fg1(nf_ + ng_); for(j = 0; j < nx_; j++) x1[j] = 0.0; // index in col_order_jac_ of next entry ell = 0; k = col_order_jac_[ell]; for(j = 0; j < nx_; j++) { // compute j-th column of Jacobian of g(x) x1[j] = 1.0; fg1 = adfun_.Forward(1, x1); while( ell < nk && col_jac_[k] <= j ) { CPPAD_ASSERT_UNKNOWN( col_jac_[k] == j ); i = row_jac_[k]; CPPAD_ASSERT_UNKNOWN( i >= nf_ ) values[k] = fg1[i]; ell++; if( ell < nk ) k = col_order_jac_[ell]; } x1[j] = 0.0; } } else { // user reverse mode size_t nfg = nf_ + ng_; // user reverse mode Dvector w(nfg), dw(nx_); for(i = 0; i < nfg; i++) w[i] = 0.0; // index in row_jac_ of next entry k = 0; for(i = nf_; i < nfg; i++) { // compute i-th row of Jacobian of g(x) w[i] = 1.0; dw = adfun_.Reverse(1, w); while( k < nk && row_jac_[k] <= i ) { CPPAD_ASSERT_UNKNOWN( row_jac_[k] == i ); j = col_jac_[k]; values[k] = dw[j]; k++; } w[i] = 0.0; } } return true; } // ----------------------------------------------------------------------- /*! Evaluate the Hessian of the Lagragian \section The_Hessian_of_the_Lagragian The Hessian of the Lagragian The Hessian of the Lagragian is defined as \f[ H(x, \sigma, \lambda ) = \sigma \nabla^2 f(x) + \sum_{i=0}^{m-1} \lambda_i \nabla^2 g(x)_i \f] \param[in] n is the dimension of the argument space for g(x); i.e., must be equal nx_. \param x if values is not NULL, x is a vector of size nx_ containing the point at which to evaluate the Hessian of the Lagragian. \param[in] new_x is false if the previous call to any one of the \ref Evaluation_Methods used the same value for x. \param[in] obj_factor the value \f$ \sigma \f$ multiplying the Hessian of f(x) in the expression for \ref The_Hessian_of_the_Lagragian. \param[in] m is the dimension of the range space for g(x); i.e., must be equal to ng_. \param[in] lambda if values is not NULL, lambda is a vector of size ng_ specifing the value of \f$ \lambda \f$ in the expression for \ref The_Hessian_of_the_Lagragian. \param[in] new_lambda is true if the previous call to eval_h had the same value for lambda and false otherwise. (Not currently used.) \param[in] nele_hess is the number of possibly non-zero elements in the Hessian of the Lagragian; i.e., must be equal to nx_*(nx_+1)/2. \param iRow if values is not NULL, iRow is not defined. if values is NULL, iRow is a vector with size nele_hess. The input value of its elements does not matter. On output, For k = 0 , ... , nele_hess-1, iRow[k] is the base zero row index for the k-th possibly non-zero entry in the Hessian fo the Lagragian. \param jCol if values is not NULL, jCol is not defined. if values is NULL, jCol is a vector with size nele_hess. The input value of its elements does not matter. On output, For k = 0 , ... , nele_hess-1, jCol[k] is the base zero column index for the k-th possibly non-zero entry in the Hessian of the Lagragian. \param values if values is not NULL, it is a vector with size nele_hess. The input value of its elements does not matter. On output, For k = 0 , ... , nele_hess-1, values[k] is the value for the k-th possibly non-zero entry in the Hessian of the Lagragian. \return The return value is always true; see \ref Evaluation_Methods. */ virtual bool eval_h( Index n , const Number* x , bool new_x , Number obj_factor , Index m , const Number* lambda , bool new_lambda , Index nele_hess , Index* iRow , Index* jCol , Number* values ) { size_t i, j, k; CPPAD_ASSERT_UNKNOWN(static_cast(m) == ng_ ); CPPAD_ASSERT_UNKNOWN(static_cast(n) == nx_ ); // size_t nk = row_hes_.size(); CPPAD_ASSERT_UNKNOWN( static_cast(nele_hess) == nk ); // if( new_x ) cache_new_x(x); // if( values == NULL ) { for(k = 0; k < nk; k++) { i = row_hes_[k]; j = col_hes_[k]; iRow[k] = static_cast(i); jCol[k] = static_cast(j); } return true; } // if( nk == 0 ) return true; // weigting vector for Lagragian Dvector w(nf_ + ng_); for(i = 0; i < nf_; i++) w[i] = obj_factor; for(i = 0; i < ng_; i++) w[i + nf_] = lambda[i]; // if( sparse_forward_ | sparse_reverse_ ) { Dvector hes(nk); adfun_.SparseHessian( x0_, w, pattern_hes_, row_hes_, col_hes_, hes, work_hes_ ); for(k = 0; k < nk; k++) values[k] = hes[k]; } else { Dvector hes(nx_ * nx_); hes = adfun_.Hessian(x0_, w); for(k = 0; k < nk; k++) { i = row_hes_[k]; j = col_hes_[k]; values[k] = hes[i * nx_ + j]; } } return true; } // ---------------------------------------------------------------------- /*! Pass solution information from Ipopt to users solution structure. \param[in] status is value that the Ipopt solution status which gets mapped to a correponding value for \n solution_.status \param[in] n is the dimension of the domain space for f(x) and g(x); i.e., it must be equal to nx_. \param[in] x is a vector with size nx_ specifing the final solution. This is the output value for \n solution_.x \param[in] z_L is a vector with size nx_ specifing the Lagragian multipliers for the constraint \f$ x^l \leq x \f$. This is the output value for \n solution_.zl \param[in] z_U is a vector with size nx_ specifing the Lagragian multipliers for the constraint \f$ x \leq x^u \f$. This is the output value for \n solution_.zu \param[in] m is the dimension of the range space for g(x). i.e., it must be equal to ng_. \param[in] g is a vector with size ng_ containing the value of the constraint function g(x) at the final solution x. This is the output value for \n solution_.g \param[in] lambda is a vector with size ng_ specifing the Lagragian multipliers for the constraints \f$ g^l \leq g(x) \leq g^u \f$. This is the output value for \n solution_.lambda \param[in] obj_value is the value of the objective function f(x) at the final solution x. This is the output value for \n solution_.obj_value \param[in] ip_data is unspecified (by Ipopt) and hence not used. \param[in] ip_cq is unspecified (by Ipopt) and hence not used. \par solution_[out] this is a reference to the solution argument in the constructor for solve_callback. The results are stored here (see documentation above). */ virtual void finalize_solution( Ipopt::SolverReturn status , Index n , const Number* x , const Number* z_L , const Number* z_U , Index m , const Number* g , const Number* lambda , Number obj_value , const Ipopt::IpoptData* ip_data , Ipopt::IpoptCalculatedQuantities* ip_cq ) { size_t i, j; CPPAD_ASSERT_UNKNOWN(static_cast(n) == nx_ ); CPPAD_ASSERT_UNKNOWN(static_cast(m) == ng_ ); switch(status) { // convert status from Ipopt enum to solve_result enum case Ipopt::SUCCESS: solution_.status = solve_result::success; break; case Ipopt::MAXITER_EXCEEDED: solution_.status = solve_result::maxiter_exceeded; break; case Ipopt::STOP_AT_TINY_STEP: solution_.status = solve_result::stop_at_tiny_step; break; case Ipopt::STOP_AT_ACCEPTABLE_POINT: solution_.status = solve_result::stop_at_acceptable_point; break; case Ipopt::LOCAL_INFEASIBILITY: solution_.status = solve_result::local_infeasibility; break; case Ipopt::USER_REQUESTED_STOP: solution_.status = solve_result::user_requested_stop; break; case Ipopt::DIVERGING_ITERATES: solution_.status = solve_result::diverging_iterates; break; case Ipopt::RESTORATION_FAILURE: solution_.status = solve_result::restoration_failure; break; case Ipopt::ERROR_IN_STEP_COMPUTATION: solution_.status = solve_result::error_in_step_computation; break; case Ipopt::INVALID_NUMBER_DETECTED: solution_.status = solve_result::invalid_number_detected; break; case Ipopt::INTERNAL_ERROR: solution_.status = solve_result::internal_error; break; default: solution_.status = solve_result::unknown; } solution_.x.resize(nx_); solution_.zl.resize(nx_); solution_.zu.resize(nx_); for(j = 0; j < nx_; j++) { solution_.x[j] = x[j]; solution_.zl[j] = z_L[j]; solution_.zu[j] = z_U[j]; } solution_.g.resize(ng_); solution_.lambda.resize(ng_); for(i = 0; i < ng_; i++) { solution_.g[i] = g[i]; solution_.lambda[i] = lambda[i]; } solution_.obj_value = obj_value; return; } }; } // end namespace ipopt } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/ipopt/solve_result.hpp0000644000176200001440000000361014536067013020762 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SOLVE_RESULT_INCLUDED # define CPPAD_SOLVE_RESULT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE namespace ipopt { /*! \file solve_result.hpp Class that contains information about solve problem result */ /*! Class that contains information about solve problem result \tparam Dvector a simple vector with elements of type double */ template class solve_result { public: /// possible values for the result status enum status_type { not_defined, success, maxiter_exceeded, stop_at_tiny_step, stop_at_acceptable_point, local_infeasibility, user_requested_stop, feasible_point_found, diverging_iterates, restoration_failure, error_in_step_computation, invalid_number_detected, too_few_degrees_of_freedom, internal_error, unknown }; /// possible values for solution status status_type status; /// the approximation solution Dvector x; /// Lagrange multipliers corresponding to lower bounds on x Dvector zl; /// Lagrange multipliers corresponding to upper bounds on x Dvector zu; /// value of g(x) Dvector g; /// Lagrange multipliers correspondiing constraints on g(x) Dvector lambda; /// value of f(x) double obj_value; /// constructor initializes solution status as not yet defined solve_result(void) { status = not_defined; } }; } // end namespace ipopt } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/OdeGear.h0000644000176200001440000000005214113627761016047 0ustar liggesusers/* $Id$ */ # include "cppad/ode_gear.hpp" TMB/inst/include/cppad/CheckSimpleVector.h0000644000176200001440000000006514113627761020117 0ustar liggesusers/* $Id$ */ # include "cppad/check_simple_vector.hpp" TMB/inst/include/cppad/LuSolve.h0000644000176200001440000000005214113627761016132 0ustar liggesusers/* $Id$ */ # include "cppad/lu_solve.hpp" TMB/inst/include/cppad/lu_invert.hpp0000644000176200001440000001443414536067012017115 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_LU_INVERT_INCLUDED # define CPPAD_LU_INVERT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin LuInvert$$ $escape #$$ $spell cppad.hpp Lu Cpp jp ip const namespace typename etmp $$ $index LuInvert$$ $index linear, invert Lu equation$$ $index equation, Lu invert$$ $section Invert an LU Factored Equation$$ $pre $$ $head Syntax$$ $code# include $$ $pre $$ $codei%LuInvert(%ip%, %jp%, %LU%, %X%)%$$ $head Description$$ Solves the matrix equation $icode%A% * %X% = %B%$$ using an LU factorization computed by $cref LuFactor$$. $head Include$$ The file $code cppad/lu_invert.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Matrix Storage$$ All matrices are stored in row major order. To be specific, if $latex Y$$ is a vector that contains a $latex p$$ by $latex q$$ matrix, the size of $latex Y$$ must be equal to $latex p * q $$ and for $latex i = 0 , \ldots , p-1$$, $latex j = 0 , \ldots , q-1$$, $latex \[ Y_{i,j} = Y[ i * q + j ] \] $$ $head ip$$ The argument $icode ip$$ has prototype $codei% const %SizeVector% &%ip% %$$ (see description for $icode SizeVector$$ in $cref/LuFactor/LuFactor/SizeVector/$$ specifications). The size of $icode ip$$ is referred to as $icode n$$ in the specifications below. The elements of $icode ip$$ determine the order of the rows in the permuted matrix. $head jp$$ The argument $icode jp$$ has prototype $codei% const %SizeVector% &%jp% %$$ (see description for $icode SizeVector$$ in $cref/LuFactor/LuFactor/SizeVector/$$ specifications). The size of $icode jp$$ must be equal to $icode n$$. The elements of $icode jp$$ determine the order of the columns in the permuted matrix. $head LU$$ The argument $icode LU$$ has the prototype $codei% const %FloatVector% &%LU% %$$ and the size of $icode LU$$ must equal $latex n * n$$ (see description for $icode FloatVector$$ in $cref/LuFactor/LuFactor/FloatVector/$$ specifications). $subhead L$$ We define the lower triangular matrix $icode L$$ in terms of $icode LU$$. The matrix $icode L$$ is zero above the diagonal and the rest of the elements are defined by $codei% %L%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ for $latex i = 0 , \ldots , n-1$$ and $latex j = 0 , \ldots , i$$. $subhead U$$ We define the upper triangular matrix $icode U$$ in terms of $icode LU$$. The matrix $icode U$$ is zero below the diagonal, one on the diagonal, and the rest of the elements are defined by $codei% %U%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ for $latex i = 0 , \ldots , n-2$$ and $latex j = i+1 , \ldots , n-1$$. $subhead P$$ We define the permuted matrix $icode P$$ in terms of the matrix $icode L$$ and the matrix $icode U$$ by $icode%P% = %L% * %U%$$. $subhead A$$ The matrix $icode A$$, which defines the linear equations that we are solving, is given by $codei% %P%(%i%, %j%) = %A%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ (Hence $icode LU$$ contains a permuted factorization of the matrix $icode A$$.) $head X$$ The argument $icode X$$ has prototype $codei% %FloatVector% &%X% %$$ (see description for $icode FloatVector$$ in $cref/LuFactor/LuFactor/FloatVector/$$ specifications). The matrix $icode X$$ must have the same number of rows as the matrix $icode A$$. The input value of $icode X$$ is the matrix $icode B$$ and the output value solves the matrix equation $icode%A% * %X% = %B%$$. $children% example/lu_invert.cpp% omh/lu_invert_hpp.omh %$$ $head Example$$ The file $cref lu_solve.hpp$$ is a good example usage of $code LuFactor$$ with $code LuInvert$$. The file $cref lu_invert.cpp$$ contains an example and test of using $code LuInvert$$ by itself. It returns true if it succeeds and false otherwise. $head Source$$ The file $cref lu_invert.hpp$$ contains the current source code that implements these specifications. $end -------------------------------------------------------------------------- */ // BEGIN C++ # include # include # include namespace CppAD { // BEGIN CppAD namespace // LuInvert template void LuInvert( const SizeVector &ip, const SizeVector &jp, const FloatVector &LU, FloatVector &B ) { size_t k; // column index in X size_t p; // index along diagonal in LU size_t i; // row index in LU and X typedef typename FloatVector::value_type Float; // check numeric type specifications CheckNumericType(); // check simple vector class specifications CheckSimpleVector(); CheckSimpleVector(); Float etmp; size_t n = ip.size(); CPPAD_ASSERT_KNOWN( size_t(jp.size()) == n, "Error in LuInvert: jp must have size equal to n * n" ); CPPAD_ASSERT_KNOWN( size_t(LU.size()) == n * n, "Error in LuInvert: Lu must have size equal to n * m" ); size_t m = size_t(B.size()) / n; CPPAD_ASSERT_KNOWN( size_t(B.size()) == n * m, "Error in LuSolve: B must have size equal to a multiple of n" ); // temporary storage for reordered solution FloatVector x(n); // loop over equations for(k = 0; k < m; k++) { // invert the equation c = L * b for(p = 0; p < n; p++) { // solve for c[p] etmp = B[ ip[p] * m + k ] / LU[ ip[p] * n + jp[p] ]; B[ ip[p] * m + k ] = etmp; // subtract off effect on other variables for(i = p+1; i < n; i++) B[ ip[i] * m + k ] -= etmp * LU[ ip[i] * n + jp[p] ]; } // invert the equation x = U * c p = n; while( p > 0 ) { --p; etmp = B[ ip[p] * m + k ]; x[ jp[p] ] = etmp; for(i = 0; i < p; i++ ) B[ ip[i] * m + k ] -= etmp * LU[ ip[i] * n + jp[p] ]; } // copy reordered solution into B for(i = 0; i < n; i++) B[i * m + k] = x[i]; } return; } } // END CppAD namespace // END C++ # endif TMB/inst/include/cppad/CppAD.h0000644000176200001440000000004714113627761015474 0ustar liggesusers/* $Id$ */ # include "cppad/cppad.hpp" TMB/inst/include/cppad/local/0000755000176200001440000000000014536067013015462 5ustar liggesusersTMB/inst/include/cppad/local/div_eq.hpp0000644000176200001440000000507014536067013017444 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DIV_EQ_INCLUDED # define CPPAD_DIV_EQ_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD& AD::operator /= (const AD &right) { // compute the Base part Base left; left = value_; value_ /= right.value_; // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return *this; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_left = tape_id_ == tape_id; bool var_right = right.tape_id_ == tape_id; if( var_left ) { if( var_right ) { // this = variable / variable CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(taddr_, right.taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(DivvvOp); // make this a variable CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id ); } else if( IdenticalOne( right.value_ ) ) { // this = variable * 1 } else { // this = variable / parameter CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(taddr_, p); // put operator in the tape taddr_ = tape->Rec_.PutOp(DivvpOp); // make this a variable CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id ); } } else if( var_right ) { if( IdenticalZero(left) ) { // this = 0 / variable } else { // this = parameter / variable CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(left); tape->Rec_.PutArg(p, right.taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(DivpvOp); // make this a variable tape_id_ = tape_id; } } return *this; } CPPAD_FOLD_ASSIGNMENT_OPERATOR(/=) } // END CppAD namespace # endif TMB/inst/include/cppad/local/sparse_pattern.hpp0000644000176200001440000000326214536067013021230 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_PATTERN_INCLUDED # define CPPAD_SPARSE_PATTERN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // necessary definitions # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sparse_pattern.hpp Determine internal spasity pattern from correpsonding element type. */ /*! Template structure used obtain the internal sparsity pattern type form the corresponding element type. The general form is not valid, must use a specialization. \tparam Element_type type of an element in the sparsity structrue. \par internal_sparsity::pattern_type is the type of the corresponding internal sparsity pattern. */ template struct internal_sparsity; /*! Specilization for \c bool elements. */ template <> struct internal_sparsity { typedef sparse_pack pattern_type; }; /*! Specilization for std::set elements. */ template <> struct internal_sparsity< std::set > { typedef CPPAD_INTERNAL_SPARSE_SET pattern_type; }; } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/rev_two.hpp0000644000176200001440000001432414536067013017664 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_REV_TWO_INCLUDED # define CPPAD_REV_TWO_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin RevTwo$$ $spell ddw typename Taylor const $$ $index partial, second order driver$$ $index second, order partial driver$$ $index driver, second order partial$$ $index easy, partial$$ $index driver, easy partial$$ $index partial, easy$$ $section Reverse Mode Second Partial Derivative Driver$$ $head Syntax$$ $icode%ddw% = %f%.RevTwo(%x%, %i%, %j%)%$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. The syntax above sets $latex \[ ddw [ k * p + \ell ] = \DD{ F_{i[ \ell ]} }{ x_{j[ \ell ]} }{ x_k } (x) \] $$ for $latex k = 0 , \ldots , n-1$$ and $latex \ell = 0 , \ldots , p$$, where $latex p$$ is the size of the vectors $icode i$$ and $icode j$$. $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/RevTwo Uses Forward/RevTwo/RevTwo Uses Forward/$$ below). $head x$$ The argument $icode x$$ has prototype $codei% const %VectorBase% &%x% %$$ (see $cref/VectorBase/RevTwo/VectorBase/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies that point at which to evaluate the partial derivatives listed above. $head i$$ The argument $icode i$$ has prototype $codei% const %VectorSize_t% &%i% %$$ (see $cref/VectorSize_t/RevTwo/VectorSize_t/$$ below) We use $icode p$$ to denote the size of the vector $icode i$$. All of the indices in $icode i$$ must be less than $icode m$$, the dimension of the $cref/range/seq_property/Range/$$ space for $icode f$$; i.e., for $latex \ell = 0 , \ldots , p-1$$, $latex i[ \ell ] < m$$. $head j$$ The argument $icode j$$ has prototype $codei% const %VectorSize_t% &%j% %$$ (see $cref/VectorSize_t/RevTwo/VectorSize_t/$$ below) and its size must be equal to $icode p$$, the size of the vector $icode i$$. All of the indices in $icode j$$ must be less than $icode n$$; i.e., for $latex \ell = 0 , \ldots , p-1$$, $latex j[ \ell ] < n$$. $head ddw$$ The result $icode ddw$$ has prototype $codei% %VectorBase% %ddw% %$$ (see $cref/VectorBase/RevTwo/VectorBase/$$ below) and its size is $latex n * p$$. It contains the requested partial derivatives; to be specific, for $latex k = 0 , \ldots , n - 1 $$ and $latex \ell = 0 , \ldots , p - 1$$ $latex \[ ddw [ k * p + \ell ] = \DD{ F_{i[ \ell ]} }{ x_{j[ \ell ]} }{ x_k } (x) \] $$ $head VectorBase$$ The type $icode VectorBase$$ must be a $cref SimpleVector$$ class with $cref/elements of type Base/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head VectorSize_t$$ The type $icode VectorSize_t$$ must be a $cref SimpleVector$$ class with $cref/elements of type size_t/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head RevTwo Uses Forward$$ After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After a call to $code RevTwo$$, the zero order Taylor coefficients correspond to $icode%f%.Forward(0, %x%)%$$ and the other coefficients are unspecified. $head Examples$$ $children% example/rev_two.cpp %$$ The routine $cref/RevTwo/rev_two.cpp/$$ is both an example and test. It returns $code true$$, if it succeeds and $code false$$ otherwise. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template template VectorBase ADFun::RevTwo( const VectorBase &x, const VectorSize_t &i, const VectorSize_t &j) { size_t i1; size_t j1; size_t k; size_t l; size_t n = Domain(); size_t m = Range(); size_t p = i.size(); // check VectorBase is Simple Vector class with Base elements CheckSimpleVector(); // check VectorSize_t is Simple Vector class with size_t elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( x.size() == n, "RevTwo: Length of x not equal domain dimension for f." ); CPPAD_ASSERT_KNOWN( i.size() == j.size(), "RevTwo: Lenght of the i and j vectors are not equal." ); // point at which we are evaluating the second partials Forward(0, x); // dimension the return value VectorBase ddw(n * p); // direction vector in argument space VectorBase dx(n); for(j1 = 0; j1 < n; j1++) dx[j1] = Base(0); // direction vector in range space VectorBase w(m); for(i1 = 0; i1 < m; i1++) w[i1] = Base(0); // place to hold the results of a reverse calculation VectorBase r(n * 2); // check the indices in i and j for(l = 0; l < p; l++) { i1 = i[l]; j1 = j[l]; CPPAD_ASSERT_KNOWN( i1 < m, "RevTwo: an eleemnt of i not less than range dimension for f." ); CPPAD_ASSERT_KNOWN( j1 < n, "RevTwo: an element of j not less than domain dimension for f." ); } // loop over all forward directions for(j1 = 0; j1 < n; j1++) { // first order forward mode calculation done bool first_done = false; for(l = 0; l < p; l++) if( j[l] == j1 ) { if( ! first_done ) { first_done = true; // first order forward mode in j1 direction dx[j1] = Base(1); Forward(1, dx); dx[j1] = Base(0); } // execute a reverse in this component direction i1 = i[l]; w[i1] = Base(1); r = Reverse(2, w); w[i1] = Base(0); // place the reverse result in return value for(k = 0; k < n; k++) ddw[k * p + l] = r[k * 2 + 1]; } } return ddw; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/forward2sweep.hpp0000644000176200001440000005221314536067013020770 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FORWARD2SWEEP_INCLUDED # define CPPAD_FORWARD2SWEEP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file forward2sweep.hpp Compute one Taylor coefficient for each direction requested. */ /* \def CPPAD_ATOMIC_CALL This avoids warnings when NDEBUG is defined and user_ok is not used. If NDEBUG is defined, this resolves to \code user_atom->forward \endcode otherwise, it respolves to \code user_ok = user_atom->forward \endcode This macro is undefined at the end of this file to facillitate its use with a different definition in other files. */ # ifdef NDEBUG # define CPPAD_ATOMIC_CALL user_atom->forward # else # define CPPAD_ATOMIC_CALL user_ok = user_atom->forward # endif /*! \def CPPAD_FORWARD2SWEEP_TRACE This value is either zero or one. Zero is the normal operational value. If it is one, a trace of every forward2sweep computation is printed. */ # define CPPAD_FORWARD2SWEEP_TRACE 0 /*! Compute multiple directions forward mode Taylor coefficients. \tparam Base The type used during the forward mode computations; i.e., the corresponding recording of operations used the type AD. \param q is the order of the Taylor coefficients that are computed during this call; q > 0. \param r is the number of Taylor coefficients that are computed during this call. \param n is the number of independent variables on the tape. \param numvar is the total number of variables on the tape. This is also equal to the number of rows in the matrix taylor; i.e., play->num_var_rec(). \param play The information stored in play is a recording of the operations corresponding to the function \f[ F : {\bf R}^n \rightarrow {\bf R}^m \f] where \f$ n \f$ is the number of independent variables and \f$ m \f$ is the number of dependent variables. \n \n The object play is effectly constant. The exception to this is that while palying back the tape the object play holds information about the current location with in the tape and this changes during palyback. \param J Is the number of columns in the coefficient matrix taylor. This must be greater than or equal one. \param taylor \n \b Input: For i = 1 , ... , numvar-1, taylor[ (J-1)*r*i + i + 0 ] is the zero order Taylor coefficient corresponding to the i-th variable and all directions. For i = 1 , ... , numvar-1, For k = 1 , ... , q-1, ell = 0 , ... , r-1, taylor[ (J-1)*r*i + i + (k-1)*r + ell + 1 ] is the k-th order Taylor coefficient corresponding to the i-th variabel and ell-th direction. \n \n \b Input: For i = 1 , ... , n, ell = 0 , ... , r-1, taylor[ (J-1)*r*i + i + (q-1)*r + ell + 1 ] is the q-th order Taylor coefficient corresponding to the i-th variable and ell-th direction (these are the independent varaibles). \n \n \b Output: For i = n+1 , ... , numvar-1, ell = 0 , ... , r-1, taylor[ (J-1)*r*i + i + (q-1)*r + ell + 1 ] is the q-th order Taylor coefficient corresponding to the i-th variable and ell-th direction. \param cskip_op Is a vector with size play->num_op_rec(). If cskip_op[i] is true, the operator with index i does not affect any of the dependent variable (given the value of the independent variables). \param var_by_load_op is a vector with size play->num_load_op_rec(). It is the variable index corresponding to each the load instruction. In the case where the index is zero, the instruction corresponds to a parameter (not variable). */ template void forward2sweep( const size_t q, const size_t r, const size_t n, const size_t numvar, player* play, const size_t J, Base* taylor, const bool* cskip_op, const pod_vector& var_by_load_op ) { CPPAD_ASSERT_UNKNOWN( q > 0 ); CPPAD_ASSERT_UNKNOWN( J >= q + 1 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); // used to avoid compiler errors until all operators are implemented size_t p = q; // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; // operation argument indices const addr_t* arg = CPPAD_NULL; // work space used by UserOp. vector user_vx; // empty vecotor vector user_vy; // empty vecotor vector user_tx_one; // argument vector Taylor coefficients vector user_tx_all; vector user_ty_one; // result vector Taylor coefficients vector user_ty_all; size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end, user_trace } user_state = user_start; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // temporary indices size_t i, j, k, ell; // number of orders for this user calculation // (not needed for order zero) const size_t user_q1 = q+1; // variable indices for results vector // (done differently for order zero). vector user_iy; // skip the BeginOp at the beginning of the recording play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD2SWEEP_TRACE Rcout << std::endl; CppAD::vector Z_vec(q+1); # endif bool more_operators = true; while(more_operators) { // this op play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var); // check if we are skipping this operation while( cskip_op[i_op] ) { if( op == CSumOp ) { // CSumOp has a variable number of arguments play->forward_csum(op, arg, i_op, i_var); } CPPAD_ASSERT_UNKNOWN( op != CSkipOp ); // if( op == CSkipOp ) // { // CSkip has a variable number of arguments // play->forward_cskip(op, arg, i_op, i_var); // } play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); } // action depends on the operator switch( op ) { case AbsOp: forward_abs_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_addpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CExpOp: forward_cond_op_dir( q, r, i_var, arg, num_par, parameter, J, taylor ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op_dir(q, r, i_var, arg[0], J, taylor); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. play->forward_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_csum_op_dir( q, r, i_var, arg, num_par, parameter, J, taylor ); play->forward_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case DisOp: forward_dis_op(p, q, r, i_var, arg, J, taylor); break; // ------------------------------------------------- case DivvvOp: forward_divvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_divpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_divvp_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case EndOp: // needed for sparse_jacobian test CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case ExpOp: forward_exp_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // ------------------------------------------------- case LdpOp: case LdvOp: forward_load_op( play, op, p, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); break; // --------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_UNKNOWN(q > 0 ); break; // ------------------------------------------------- case LogOp: forward_log_op_dir(q, r, i_var, arg[0], J, taylor); break; // --------------------------------------------------- case MulvvOp: forward_mulvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_mulpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case ParOp: k = i_var*(J-1)*r + i_var + (q-1)*r + 1; for(ell = 0; ell < r; ell++) taylor[k + ell] = Base(0); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_powpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_powvp_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_UNKNOWN(q > 0); break; // ------------------------------------------------- case SignOp: // sign(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sign_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case StppOp: case StpvOp: case StvpOp: case StvvOp: CPPAD_ASSERT_UNKNOWN(q > 0 ); break; // ------------------------------------------------- case SubvvOp: forward_subvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_subpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_subvp_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tan_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tanh_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_tx_one.size() != user_n * user_q1) user_tx_one.resize(user_n * user_q1); if( user_tx_all.size() != user_n * (q * r + 1) ) user_tx_all.resize(user_n * (q * r + 1)); // if(user_ty_one.size() != user_m * user_q1) user_ty_one.resize(user_m * user_q1); if( user_ty_all.size() != user_m * (q * r + 1) ) user_ty_all.resize(user_m * (q * r + 1)); // if(user_iy.size() != user_m) user_iy.resize(user_m); user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); for(ell = 0; ell < r; ell++) { // set user_tx for(j = 0; j < user_n; j++) { size_t j_all = j * (q * r + 1); size_t j_one = j * user_q1; user_tx_one[j_one+0] = user_tx_all[j_all+0]; for(k = 1; k < user_q1; k++) { size_t k_all = j_all + (k-1)*r+1+ell; size_t k_one = j_one + k; user_tx_one[k_one] = user_tx_all[k_all]; } } // set user_ty for(i = 0; i < user_m; i++) { size_t i_all = i * (q * r + 1); size_t i_one = i * user_q1; user_ty_one[i_one+0] = user_ty_all[i_all+0]; for(k = 1; k < q; k++) { size_t k_all = i_all + (k-1)*r+1+ell; size_t k_one = i_one + k; user_ty_one[k_one] = user_ty_all[k_all]; } } CPPAD_ATOMIC_CALL( q, q, user_vx, user_vy, user_tx_one, user_ty_one ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base.forward: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(i = 0; i < user_m; i++) { if( user_iy[i] > 0 ) { size_t i_taylor = user_iy[i]*((J-1)*r+1); size_t q_taylor = i_taylor + (q-1)*r+1+ell; size_t q_one = i * user_q1 + q; taylor[q_taylor] = user_ty_one[q_one]; } } } # if CPPAD_FORWARD2SWEEP_TRACE user_state = user_trace; # else user_state = user_start; # endif } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); user_tx_all[user_j*(q*r+1) + 0] = parameter[ arg[0]]; for(ell = 0; ell < r; ell++) for(k = 1; k < user_q1; k++) user_tx_all[user_j*(q*r+1) + (k-1)*r+1+ell] = Base(0); ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); user_tx_all[user_j*(q*r+1)+0] = taylor[arg[0]*((J-1)*r+1)+0]; for(ell = 0; ell < r; ell++) { for(k = 1; k < user_q1; k++) { user_tx_all[user_j*(q*r+1) + (k-1)*r+1+ell] = taylor[arg[0]*((J-1)*r+1) + (k-1)*r+1+ell]; } } ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = 0; user_ty_all[user_i*(q*r+1) + 0] = parameter[ arg[0]]; for(ell = 0; ell < r; ell++) for(k = 1; k < user_q1; k++) user_ty_all[user_i*(q*r+1) + (k-1)*r+1+ell] = Base(0); user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = i_var; user_ty_all[user_i*(q*r+1)+0] = taylor[i_var*((J-1)*r+1)+0]; for(ell = 0; ell < r; ell++) { for(k = 1; k < user_q1; k++) { user_ty_all[user_i*(q*r+1) + (k-1)*r+1+ell] = taylor[i_var*((J-1)*r+1) + (k-1)*r+1+ell]; } } user_i++; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FORWARD2SWEEP_TRACE if( user_state == user_trace ) { user_state = user_start; CPPAD_ASSERT_UNKNOWN( op == UserOp ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 ); for(i = 0; i < user_m; i++) if( user_iy[i] > 0 ) { size_t i_tmp = (i_op + i) - user_m; printOp( Rcout, play, i_tmp, user_iy[i], UsrrvOp, CPPAD_NULL ); Base* Z_tmp = taylor + user_iy[i]*((J-1) * r + 1); { Z_vec[0] = Z_tmp[0]; for(ell = 0; ell < r; ell++) { Rcout << std::endl << " "; for(size_t p_tmp = 1; p_tmp <= q; p_tmp++) Z_vec[p_tmp] = Z_tmp[(p_tmp-1)*r+ell+1]; printOpResult( Rcout, q + 1, Z_vec.data(), 0, (Base *) CPPAD_NULL ); } } Rcout << std::endl; } } const addr_t* arg_tmp = arg; if( op == CSumOp ) arg_tmp = arg - arg[-1] - 4; if( op == CSkipOp ) arg_tmp = arg - arg[-1] - 7; if( op != UsrrvOp ) { printOp( Rcout, play, i_op, i_var, op, arg_tmp ); Base* Z_tmp = CPPAD_NULL; if( op == UsravOp ) Z_tmp = taylor + arg[0]*((J-1) * r + 1); else if( NumRes(op) > 0 ) Z_tmp = taylor + i_var*((J-1)*r + 1); if( Z_tmp != CPPAD_NULL ) { Z_vec[0] = Z_tmp[0]; for(ell = 0; ell < r; ell++) { Rcout << std::endl << " "; for(size_t p_tmp = 1; p_tmp <= q; p_tmp++) Z_vec[p_tmp] = Z_tmp[ (p_tmp-1)*r + ell + 1]; printOpResult( Rcout, q + 1, Z_vec.data(), 0, (Base *) CPPAD_NULL ); } } Rcout << std::endl; } } Rcout << std::endl; # else } # endif CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( i_var + 1 == play->num_var_rec() ); return; } // preprocessor symbols that are local to this file # undef CPPAD_FORWARD2SWEEP_TRACE # undef CPPAD_ATOMIC_CALL } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/unary_minus.hpp0000644000176200001440000000461414536067013020551 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_UNARY_MINUS_INCLUDED # define CPPAD_UNARY_MINUS_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin UnaryMinus$$ $spell Vec const inline $$ $index unary, AD minus operator$$ $index AD, unary minus operator$$ $index minus, AD unary operator$$ $index -, AD unary operator$$ $section AD Unary Minus Operator$$ $head Syntax$$ $icode%y% = - %x%$$ $head Purpose$$ Computes the negative of $icode x$$. $head Base$$ The operation in the syntax above must be supported for the case where the operand is a $code const$$ $icode Base$$ object. $head x$$ The operand $icode x$$ has one of the following prototypes $codei% const AD<%Base%> &%x% const VecAD<%Base%>::reference &%x% %$$ $head y$$ The result $icode y$$ has type $codei% AD<%Base%> %y% %$$ It is equal to the negative of the operand $icode x$$. $head Operation Sequence$$ This is an AD of $icode Base$$ $cref/atomic operation/glossary/Operation/Atomic/$$ and hence is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Derivative$$ If $latex f$$ is a $cref/Base function/glossary/Base Function/$$, $latex \[ \D{[ - f(x) ]}{x} = - \D{f(x)}{x} \] $$ $head Example$$ $children% example/unary_minus.cpp %$$ The file $cref unary_minus.cpp$$ contains an example and test of this operation. $end ------------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { // Broken g++ compiler inhibits declaring unary minus a member or friend template inline AD AD::operator - (void) const { // should make a more efficient version by adding unary minus to // Operator.h (some day) AD result(0); result -= *this; return result; } template inline AD operator - (const VecAD_reference &right) { return - right.ADBase(); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/load_op.hpp0000644000176200001440000004666614536067013017632 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_LOAD_OP_INCLUDED # define CPPAD_LOAD_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file load_op.hpp Setting a variable so that it corresponds to current value of a VecAD element. */ /*! Shared documentation for zero order forward mode implementation of op = LdpOp or LdvOp (not called). The C++ source code corresponding to this operation is \verbatim z = v[x] \endverbatim where v is a VecAD vector and x is an AD index. We define the index corresponding to v[x] by \verbatim i_v_x = index_by_ind[ arg[0] + i_vec ] \endverbatim where i_vec is defined under the heading arg[1] below: \tparam Base base type for the operator; i.e., this operation was recorded using AD and computations by this routine are done using type Base. \param play is the tape that this operation appears in. This is for error detection and not used when NDEBUG is defined. \param i_z is the AD variable index corresponding to the variable z. \param arg \n arg[0] is the offset of this VecAD vector relative to the beginning of the isvar_by_ind and index)_by_ind arrays. \n \n arg[1] \n If this is the LdpOp operation (if x is a parameter), i_vec is defined by \verbatim i_vec = arg[1] \endverbatim If this is the LdvOp operation (if x is a variable), i_vec is defined by \verbatim i_vec = floor( taylor[ arg[1] * cap_order + 0 ] ) \endverbatim where floor(c) is the greatest integer less that or equal c. \n \n arg[2] Is the index of this vecad load instruction in the var_by_load_op array. \param parameter If v[x] is a parameter, parameter[ i_v_x ] is its value. This vector has size play->num_par_rec(). \param cap_order number of columns in the matrix containing the Taylor coefficients. \param taylor \n Input \n In LdvOp case, taylor[ arg[1] * cap_order + 0 ] is used to compute the index in the definition of i_vec above. If v[x] is a variable, taylor[ i_v_x * cap_order + 0 ] is the zero order Taylor coefficient for v[x]. \n \n Output \n taylor[ i_z * cap_order + 0 ] is set to the zero order Taylor coefficient for the variable z. \param isvar_by_ind If isvar_by_ind[ arg[0] + i_vec ] is true, v[x] is a variable. Otherwise it is a parameter. This vector has size play->num_vec_ind_rec(). \param index_by_ind index_by_ind[ arg[0] - 1 ] is the number of elements in the user vector containing this element. index_by_ind[ arg[0] + i_vec ] is the variable or parameter index for this element, This array has size play->num_vec_ind_rec(). \param var_by_load_op is a vector with size play->num_load_op_rec(). The input value of its elements does not matter. Upon return, it contains the variable index corresponding to each load instruction. In the case where the index is zero, the instruction corresponds to a parameter (not variable). This array has size play->num_load_op_rec(). \par Check User Errors \li In the LdvOp case check that the index is with in range; i.e. i_vec < index_by_ind[ arg[0] - 1 ]. Note that, if x is a parameter, the corresponding vector index and it does not change. In this case, the error above should be detected during tape recording. */ template inline void forward_load_op_0( player* play , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor , bool* isvar_by_ind , size_t* index_by_ind , addr_t* var_by_load_op ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Shared documentation for sparsity operations corresponding to op = LdpOp or LdvOp (not called). The C++ source code corresponding to this operation is \verbatim z = v[x] \endverbatim where v is a VecAD vector and x is an AD index. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param op is the code corresponding to this operator; i.e., LdpOp or LdvOp (only used for error checking). \param i_z is the AD variable index corresponding to the variable z; i.e., the set with index \a i_z in \a var_sparsity is the sparsity pattern correpsonding to z. \param arg \n \a arg[0] is the offset corresponding to this VecAD vector in the VecAD combined array. \param num_combined is the total number of elements in the VecAD combinded array. \param combined is the VecAD combined array. \n \n \a combined[ \a arg[0] - 1 ] is the index of the set corresponding to the vector v in \a vecad_sparsity. We use the notation i_v for this value; i.e., \verbatim i_v = combined[ \a arg[0] - 1 ] \endverbatim \param var_sparsity The set with index \a i_z in \a var_sparsity is the sparsity pattern for z. This is an output for forward mode operations, and an input for reverse mode operations. \param vecad_sparsity The set with index \a i_v is the sparsity pattern for the vector v. This is an input for forward mode operations. For reverse mode operations, the sparsity pattern for z is added to the sparsity pattern for v. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 1 \li 0 < \a arg[0] \li \a arg[0] < \a num_combined \li i_v < \a vecad_sparsity.n_set() */ template inline void sparse_load_op( OpCode op , size_t i_z , const addr_t* arg , size_t num_combined , const size_t* combined , Vector_set& var_sparsity , Vector_set& vecad_sparsity ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Zero order forward mode implementation of op = LdpOp. \copydetails forward_load_op_0 */ template inline void forward_load_p_op_0( player* play , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor , bool* isvar_by_ind , size_t* index_by_ind , addr_t* var_by_load_op ) { CPPAD_ASSERT_UNKNOWN( NumArg(LdpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(LdpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < play->num_load_op_rec() ); // Because the index is a parameter, this indexing error should have been // caught and reported to the user when the tape is recording. size_t i_vec = arg[1]; CPPAD_ASSERT_UNKNOWN( i_vec < index_by_ind[ arg[0] - 1 ] ); CPPAD_ASSERT_UNKNOWN( arg[0] + i_vec < play->num_vec_ind_rec() ); size_t i_v_x = index_by_ind[ arg[0] + i_vec ]; Base* z = taylor + i_z * cap_order; if( isvar_by_ind[ arg[0] + i_vec ] ) { CPPAD_ASSERT_UNKNOWN( i_v_x < i_z ); var_by_load_op[ arg[2] ] = i_v_x; Base* v_x = taylor + i_v_x * cap_order; z[0] = v_x[0]; } else { CPPAD_ASSERT_UNKNOWN( i_v_x < play->num_par_rec() ); var_by_load_op[ arg[2] ] = 0; Base v_x = parameter[i_v_x]; z[0] = v_x; } } /*! Zero order forward mode implementation of op = LdvOp. \copydetails forward_load_op_0 */ template inline void forward_load_v_op_0( player* play , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor , bool* isvar_by_ind , size_t* index_by_ind , addr_t* var_by_load_op ) { CPPAD_ASSERT_UNKNOWN( NumArg(LdvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(LdvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < play->num_load_op_rec() ); size_t i_vec = Integer( taylor[ arg[1] * cap_order + 0 ] ); CPPAD_ASSERT_KNOWN( i_vec < index_by_ind[ arg[0] - 1 ] , "VecAD: index during zero order forward sweep is out of range" ); CPPAD_ASSERT_UNKNOWN( arg[0] + i_vec < play->num_vec_ind_rec() ); size_t i_v_x = index_by_ind[ arg[0] + i_vec ]; Base* z = taylor + i_z * cap_order; if( isvar_by_ind[ arg[0] + i_vec ] ) { CPPAD_ASSERT_UNKNOWN( i_v_x < i_z ); var_by_load_op[ arg[2] ] = i_v_x; Base* v_x = taylor + i_v_x * cap_order; z[0] = v_x[0]; } else { CPPAD_ASSERT_UNKNOWN( i_v_x < play->num_par_rec() ); var_by_load_op[ arg[2] ] = 0; Base v_x = parameter[i_v_x]; z[0] = v_x; } } /*! Forward mode, except for zero order, for op = LdpOp or op = LdvOp The C++ source code corresponding to this operation is \verbatim z = v[x] \endverbatim where v is a VecAD vector and x is an AD or Base index. \tparam Base base type for the operator; i.e., this operation was recorded using AD and computations by this routine are done using type Base. \param play is the tape that this operation appears in. This is for error detection and not used when NDEBUG is defined. \param op is the code corresponding to this operator; i.e., LdpOp or LdvOp (only used for error checking). \param p is the lowest order of the Taylor coefficient that we are computing. \param q is the highest order of the Taylor coefficient that we are computing. \param r is the number of directions for the Taylor coefficients that we are computing. \param cap_order number of columns in the matrix containing the Taylor coefficients. \par tpv We use the notation tpv = (cap_order-1) * r + 1 which is the number of Taylor coefficients per variable \param i_z is the AD variable index corresponding to the variable z. \param arg arg[2] Is the index of this vecad load instruction in the var_by_load_op array. \param var_by_load_op is a vector with size play->num_load_op_rec(). It contains the variable index corresponding to each load instruction. In the case where the index is zero, the instruction corresponds to a parameter (not variable). \par i_var We use the notation \verbatim i_var = size_t( var_by_load_op[ arg[2] ] ) \endverbatim \param taylor \n Input \n If i_var > 0, v[x] is a variable and for k = 1 , ... , q taylor[ i_var * tpv + (k-1)*r+1+ell ] is the k-th order coefficient for v[x] in the ell-th direction, \n \n Output \n for k = p , ... , q, taylor[ i_z * tpv + (k-1)*r+1+ell ] is set to the k-order Taylor coefficient for z in the ell-th direction. */ template inline void forward_load_op( const player* play , OpCode op , size_t p , size_t q , size_t r , size_t cap_order , size_t i_z , const addr_t* arg , const addr_t* var_by_load_op , Base* taylor ) { CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( 0 < r); CPPAD_ASSERT_UNKNOWN( 0 < p); CPPAD_ASSERT_UNKNOWN( p <= q ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < play->num_load_op_rec() ); size_t i_var = size_t( var_by_load_op[ arg[2] ] ); CPPAD_ASSERT_UNKNOWN( i_var < i_z ); size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* z = taylor + i_z * num_taylor_per_var; if( i_var > 0 ) { Base* v_x = taylor + i_var * num_taylor_per_var; for(size_t ell = 0; ell < r; ell++) { for(size_t k = p; k <= q; k++) { size_t m = (k-1) * r + 1 + ell; z[m] = v_x[m]; } } } else { for(size_t ell = 0; ell < r; ell++) { for(size_t k = p; k <= q; k++) { size_t m = (k-1) * r + 1 + ell; z[m] = Base(0); } } } } /*! Reverse mode for op = LdpOp or LdvOp. The C++ source code corresponding to this operation is \verbatim z = y[x] \endverbatim where y is a VecAD vector and x is an AD or Base index. This routine is given the partial derivatives of a function G(z , y[x] , w , u ... ) and it uses them to compute the partial derivatives of \verbatim H( y[x] , w , u , ... ) = G[ z( y[x] ) , y[x] , w , u , ... ] \endverbatim \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param op is the code corresponding to this operator; i.e., LdpOp or LdvOp (only used for error checking). \param d highest order the Taylor coefficient that we are computing the partial derivative with respect to. \param i_z is the AD variable index corresponding to the variable z. \param arg \a arg[2] Is the index of this vecad load instruction in the var_by_load_op array. \param cap_order number of columns in the matrix containing the Taylor coefficients (not used). \param taylor matrix of Taylor coefficients (not used). \param nc_partial number of colums in the matrix containing all the partial derivatives (not used if \a arg[2] is zero). \param partial If \a arg[2] is zero, y[x] is a parameter and no values need to be modified; i.e., \a partial is not used. Otherwise, y[x] is a variable and: \n \n \a partial [ \a i_z * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G with respect to the k-th order Taylor coefficient for z. \n \n If \a arg[2] is not zero, \a partial [ \a arg[2] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative with respect to the k-th order Taylor coefficient for x. On input, it corresponds to the function G, and on output it corresponds to the the function H. \param var_by_load_op is a vector with size play->num_load_op_rec(). It contains the variable index corresponding to each load instruction. In the case where the index is zero, the instruction corresponds to a parameter (not variable). \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 1 \li d < cap_order \li size_t(arg[2]) < i_z */ template inline void reverse_load_op( OpCode op , size_t d , size_t i_z , const addr_t* arg , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial , const addr_t* var_by_load_op ) { size_t i_load = size_t( var_by_load_op[ arg[2] ] ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( i_load < i_z ); if( i_load > 0 ) { Base* pz = partial + i_z * nc_partial; Base* py_x = partial + i_load * nc_partial; size_t j = d + 1; while(j--) py_x[j] += pz[j]; } } /*! Forward mode sparsity operations for LdpOp and LdvOp \copydetails sparse_load_op */ template inline void forward_sparse_load_op( OpCode op , size_t i_z , const addr_t* arg , size_t num_combined , const size_t* combined , Vector_set& var_sparsity , Vector_set& vecad_sparsity ) { CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); size_t i_v = combined[ arg[0] - 1 ]; CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); var_sparsity.assignment(i_z, i_v, vecad_sparsity); return; } /*! Reverse mode Jacobian sparsity operations for LdpOp and LdvOp \copydetails sparse_load_op */ template inline void reverse_sparse_jacobian_load_op( OpCode op , size_t i_z , const addr_t* arg , size_t num_combined , const size_t* combined , Vector_set& var_sparsity , Vector_set& vecad_sparsity ) { CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); size_t i_v = combined[ arg[0] - 1 ]; CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity); return; } /*! Reverse mode Hessian sparsity operations for LdpOp and LdvOp This routine is given the sparsity patterns for G(z , v[x] , w , u ... ) and it uses them to compute the sparsity patterns for \verbatim H( v[x] , w , u , ... ) = G[ z( v[x] ) , v[x] , w , u , ... ] \endverbatim The C++ source code corresponding to this operation is \verbatim z = v[x] \endverbatim where v is a VecAD vector and x is an AD index. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param op is the code corresponding to this operator; i.e., LdpOp or LdvOp (only used for error checking). \param i_z is the AD variable index corresponding to the variable z; i.e., the set with index \a i_z in \a var_sparsity is the sparsity pattern correpsonding to z. \param arg \n \a arg[0] is the offset corresponding to this VecAD vector in the VecAD combined array. \param num_combined is the total number of elements in the VecAD combinded array. \param combined is the VecAD combined array. \n \n \a combined[ \a arg[0] - 1 ] is the index of the set corresponding to the vector v in \a vecad_sparsity. We use the notation i_v for this value; i.e., \verbatim i_v = combined[ \a arg[0] - 1 ] \endverbatim \param var_sparsity The set with index \a i_z in \a var_sparsity is the sparsity pattern for z. This is an output for forward mode operations, and an input for reverse mode operations. \param vecad_sparsity The set with index \a i_v is the sparsity pattern for the vector v. This is an input for forward mode operations. For reverse mode operations, the sparsity pattern for z is added to the sparsity pattern for v. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 1 \li 0 < \a arg[0] \li \a arg[0] < \a num_combined \li i_v < \a vecad_sparsity.n_set() \param var_jacobian \a var_jacobian[i_z] is false (true) if the Jacobian of G with respect to z is always zero (many be non-zero). \param vecad_jacobian \a vecad_jacobian[i_v] is false (true) if the Jacobian with respect to x is always zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. */ template inline void reverse_sparse_hessian_load_op( OpCode op , size_t i_z , const addr_t* arg , size_t num_combined , const size_t* combined , Vector_set& var_sparsity , Vector_set& vecad_sparsity , bool* var_jacobian , bool* vecad_jacobian ) { CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); size_t i_v = combined[ arg[0] - 1 ]; CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity); vecad_jacobian[i_v] |= var_jacobian[i_z]; return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/ad_tape.hpp0000644000176200001440000001472414536067013017600 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_AD_TAPE_INCLUDED # define CPPAD_AD_TAPE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! Class used to hold tape that records AD operations. \tparam Base An AD object is used to recording AD operations. */ template class ADTape { // Friends ============================================================= // classes ------------------------------------------------------------- friend class AD; friend class ADFun; friend class atomic_base; friend class discrete; friend class VecAD; friend class VecAD_reference; // functions ----------------------------------------------------------- // PrintFor friend void PrintFor ( const AD& flag , const char* before , const AD& var , const char* after ); // CondExpOp friend AD CondExpOp ( enum CompareOp cop , const AD &left , const AD &right , const AD &trueCase , const AD &falseCase ); // pow friend AD pow (const AD &x, const AD &y); // Parameter friend bool Parameter (const AD &u); // Variable friend bool Variable (const AD &u); // operators ----------------------------------------------------------- // arithematic binary operators friend AD operator + (const AD &left, const AD &right); friend AD operator - (const AD &left, const AD &right); friend AD operator * (const AD &left, const AD &right); friend AD operator / (const AD &left, const AD &right); // comparison operators friend bool operator < (const AD &left, const AD &right); friend bool operator <= (const AD &left, const AD &right); friend bool operator > (const AD &left, const AD &right); friend bool operator >= (const AD &left, const AD &right); friend bool operator == (const AD &left, const AD &right); friend bool operator != (const AD &left, const AD &right); // ====================================================================== // -------------------------------------------------------------------------- private: // ---------------------------------------------------------------------- // private data /*! Unique identifier for this tape. It is always greater than CPPAD_MAX_NUM_THREADS, and different for every tape (even ones that have been deleted). In addition, id_ % CPPAD_MAX_NUM_THREADS is the thread number for this tape. Set by Independent and effectively const */ tape_id_t id_; /// Number of independent variables in this tapes reconding. /// Set by Independent and effectively const size_t size_independent_; /// This is where the information is recorded. recorder Rec_; // ---------------------------------------------------------------------- // private functions // // add a parameter to the tape size_t RecordParOp(const Base &x); // see CondExp.h void RecordCondExp( enum CompareOp cop , AD &returnValue , const AD &left , const AD &right , const AD &trueCase , const AD &falseCase ); // place a VecAD object in the tape size_t AddVec( size_t length, const pod_vector& data ); public: // default constructor and destructor // public function only used by CppAD::Independent template void Independent(VectorADBase &u); template void Independent(VectorADBase &u, size_t abort_op_index); }; // --------------------------------------------------------------------------- // Private functions // /*! Place a parameter in the tape. On rare occations it is necessary to place a parameter in the tape; e.g., when it is one of the dependent variabes. \param z value of the parameter that we are placing in the tape. \return variable index (for this recording) correpsonding to the parameter. \par 2DO All these operates are preformed in \c Rec_, so we should move this routine from ADTape to recorder. */ template size_t ADTape::RecordParOp(const Base &z) { size_t z_taddr; size_t ind; CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(ParOp) == 1 ); z_taddr = Rec_.PutOp(ParOp); ind = Rec_.PutPar(z); Rec_.PutArg(ind); return z_taddr; } /*! Put initialization for a VecAD object in the tape. This routine should be called once for each VecAD object when just before it changes from a parameter to a variable. \param length size of the VecAD object. \param data initial values for the VecAD object (values before it becomes a variable). \return index of the start of this vector in the list of vector indices. The value for this vector index is the length of the vector. There are \c length indices following for this vector. The values for these vector indices are the corresponding parameter indices in the tape for the initial value of the corresponding vec_ad element. \par 2DO All these operates are preformed in \c Rec_, so we should move this routine from ADTape to recorder. */ template size_t ADTape::AddVec(size_t length, const pod_vector& data) { CPPAD_ASSERT_UNKNOWN( length > 0 ); size_t i; size_t value_index; // store the length in VecInd size_t start = Rec_.PutVecInd(length); // store indices of the values in VecInd for(i = 0; i < length; i++) { value_index = Rec_.PutPar( data[i] ); Rec_.PutVecInd( value_index ); } // return the taddr of the length (where the vector starts) return start; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/add.hpp0000644000176200001440000000554314536067013016732 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ADD_INCLUDED # define CPPAD_ADD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD operator + (const AD &left , const AD &right) { // compute the Base part of this AD object AD result; result.value_ = left.value_ + right.value_; CPPAD_ASSERT_UNKNOWN( Parameter(result) ); // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return result; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_left = left.tape_id_ == tape_id; bool var_right = right.tape_id_ == tape_id; if( var_left ) { if( var_right ) { // result = variable + variable CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(left.taddr_, right.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(AddvvOp); // make result a variable result.tape_id_ = tape_id; } else if( IdenticalZero(right.value_) ) { // result = variable + 0 result.make_variable(left.tape_id_, left.taddr_); } else { // result = variable + parameter // = parameter + variable CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(p, left.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(AddpvOp); // make result a variable result.tape_id_ = tape_id; } } else if( var_right ) { if( IdenticalZero(left.value_) ) { // result = 0 + variable result.make_variable(right.tape_id_, right.taddr_); } else { // result = parameter + variable CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(left.value_); tape->Rec_.PutArg(p, right.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(AddpvOp); // make result a variable result.tape_id_ = tape_id; } } return result; } // convert other cases into the case above CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(+) } // END CppAD namespace # endif TMB/inst/include/cppad/local/color_symmetric.hpp0000644000176200001440000002312114536067013021404 0ustar liggesusers// $Id$ # ifndef CPPAD_COLOR_SYMMETRIC_INCLUDED # define CPPAD_COLOR_SYMMETRIC_INCLUDED # include /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /*! \file color_symmetric.hpp Coloring algorithm for a symmetric sparse matrix. */ // -------------------------------------------------------------------------- /*! CppAD algorithm for determining which rows of a symmetric sparse matrix can be computed together. \tparam VectorSize is a simple vector class with elements of type size_t. \tparam VectorSet is an unspecified type with the exception that it must support the operations under pattern and the following operations where p is a VectorSet object: \n VectorSet p Constructs a new vector of sets object. \n p.resize(ns, ne) resizes \c p to ns sets with elements between zero and \c ne. All of the sets are initially empty. \n p.add_element(s, e) add element \c e to set with index \c s. \param pattern [in] Is a representation of the sparsity pattern for the matrix. Note that color_symmetric does not change the values in pattern, but it is not const because its iterator facility modifies some of its internal data. \n m = pattern.n_set() \n sets m to the number of rows (and columns) in the sparse matrix. All of the row indices are less than this value. \n n = pattern.end() \n sets n to the number of columns in the sparse matrix (which must be equal to the number of rows). All of the column indices are less than this value. \n pattern.begin(i) instructs the iterator facility to start iterating over columns in the i-th row of the sparsity pattern. \n j = pattern.next_element() Sets j to the next possibly non-zero column in the row specified by the previous call to pattern.begin. If there are no more such columns, the value pattern.end() is returned. \param row [in/out] is a vector specifying which row indices to compute. \param col [in/out] is a vector, with the same size as row, that specifies which column indices to compute. \n \n Input: For each valid index \c k, the index pair (row[k], col[k]) must be present in the sparsity pattern. It may be that some entries in the sparsity pattern do not need to be computed; i.e, do not appear in the set of (row[k], col[k]) entries. \n \n Output: On output, some of row and column indices may have been swapped \code std::swap( row[k], col[k] ) \endcode So the the the color for row[k] can be used to compute entry (row[k], col[k]). \param color [out] is a vector with size m. The input value of its elements does not matter. Upon return, it is a coloring for the rows of the sparse matrix. Note that if color[i] == m, then ther is no index k for which row[k] == i (for the return value of row). \n \n Fix any (i, j) in the sparsity pattern. Suppose that there is a row index i1 with i1 != i, color[i1] == color[i] and (i1, j) is in the sparsity pattern. If follows that for all j1 with j1 != j and color[j1] == color[j], (j1, i ) is not in the sparsity pattern. \n \n This routine tries to minimize, with respect to the choice of colors, the maximum, with respect to k, of color[ row[k] ]. */ template void color_symmetric_cppad( VectorSet& pattern , CppAD::vector& row , CppAD::vector& col , CppAD::vector& color ) { size_t o1, o2, i1, i2, j1, j2, k1, c1, c2; size_t K = row.size(); size_t m = pattern.n_set(); CPPAD_ASSERT_UNKNOWN( m == pattern.end() ); CPPAD_ASSERT_UNKNOWN( color.size() == m ); CPPAD_ASSERT_UNKNOWN( col.size() == K ); // row, column pairs that appear in ( row[k], col[k] ) CppAD::vector< std::set > pair_needed(m); std::set::iterator itr1, itr2; for(k1 = 0; k1 < K; k1++) { CPPAD_ASSERT_UNKNOWN( pattern.is_element(row[k1], col[k1]) ); pair_needed[ row[k1] ].insert( col[k1] ); pair_needed[ col[k1] ].insert( row[k1] ); } // order the rows decending by number of pairs needed CppAD::vector key(m), order2row(m); for(i1 = 0; i1 < m; i1++) { CPPAD_ASSERT_UNKNOWN( pair_needed[i1].size() <= m ); key[i1] = m - pair_needed[i1].size(); } CppAD::index_sort(key, order2row); // mapping from order index to row index CppAD::vector row2order(m); for(o1 = 0; o1 < m; o1++) row2order[ order2row[o1] ] = o1; // initial coloring color.resize(m); c1 = 0; for(o1 = 0; o1 < m; o1++) { i1 = order2row[o1]; if( pair_needed[i1].empty() ) color[i1] = m; else color[i1] = c1++; } // which colors are forbidden for this row CppAD::vector forbidden(m); // must start with row zero so that we remove results computed for it for(o1 = 0; o1 < m; o1++) // for each row that appears (in order) if( color[ order2row[o1] ] < m ) { i1 = order2row[o1]; c1 = color[i1]; // initial all colors as ok for this row // (value of forbidden for c > c1 does not matter) for(c2 = 0; c2 <= c1; c2++) forbidden[c2] = false; // ----------------------------------------------------- // Forbid grouping with rows that would destroy results that are // needed for this row. itr1 = pair_needed[i1].begin(); while( itr1 != pair_needed[i1].end() ) { // entry (i1, j1) is needed for this row j1 = *itr1; // Forbid rows i2 != i1 that have non-zero sparsity at (i2, j1). // Note that this is the same as non-zero sparsity at (j1, i2) pattern.begin(j1); i2 = pattern.next_element(); while( i2 != pattern.end() ) { c2 = color[i2]; if( c2 < c1 ) forbidden[c2] = true; i2 = pattern.next_element(); } itr1++; } // ----------------------------------------------------- // Forbid grouping with rows that this row would destroy results for for(o2 = 0; o2 < o1; o2++) { i2 = order2row[o2]; c2 = color[i2]; itr2 = pair_needed[i2].begin(); while( itr2 != pair_needed[i2].end() ) { j2 = *itr2; // row i2 needs pair (i2, j2). // Forbid grouping with i1 if (i1, j2) has non-zero sparsity if( pattern.is_element(i1, j2) ) forbidden[c2] = true; itr2++; } } // pick the color with smallest index c2 = 0; while( forbidden[c2] ) { c2++; CPPAD_ASSERT_UNKNOWN( c2 <= c1 ); } color[i1] = c2; // no longer need results that are computed by this row itr1 = pair_needed[i1].begin(); while( itr1 != pair_needed[i1].end() ) { j1 = *itr1; if( row2order[j1] > o1 ) { itr2 = pair_needed[j1].find(i1); if( itr2 != pair_needed[j1].end() ) { pair_needed[j1].erase(itr2); if( pair_needed[j1].empty() ) color[j1] = m; } } itr1++; } } // determine which sparsity entries need to be reflected for(k1 = 0; k1 < row.size(); k1++) { i1 = row[k1]; j1 = col[k1]; itr1 = pair_needed[i1].find(j1); if( itr1 == pair_needed[i1].end() ) { row[k1] = j1; col[k1] = i1; # ifndef NDEBUG itr1 = pair_needed[j1].find(i1); CPPAD_ASSERT_UNKNOWN( itr1 != pair_needed[j1].end() ); # endif } } return; } // -------------------------------------------------------------------------- /*! Colpack algorithm for determining which rows of a symmetric sparse matrix can be computed together. \copydetails color_symmetric_cppad */ template void color_symmetric_colpack( VectorSet& pattern , CppAD::vector& row , CppAD::vector& col , CppAD::vector& color ) { # if ! CPPAD_HAS_COLPACK CPPAD_ASSERT_UNKNOWN(false); return; # else size_t i, j, k; size_t m = pattern.n_set(); CPPAD_ASSERT_UNKNOWN( m == pattern.end() ); CPPAD_ASSERT_UNKNOWN( row.size() == col.size() ); // Determine number of non-zero entries in each row CppAD::vector n_nonzero(m); size_t n_nonzero_total = 0; for(i = 0; i < m; i++) { n_nonzero[i] = 0; pattern.begin(i); j = pattern.next_element(); while( j != pattern.end() ) { n_nonzero[i]++; j = pattern.next_element(); } n_nonzero_total += n_nonzero[i]; } // Allocate memory and fill in Adolc sparsity pattern CppAD::vector adolc_pattern(m); CppAD::vector adolc_memory(m + n_nonzero_total); size_t i_memory = 0; for(i = 0; i < m; i++) { adolc_pattern[i] = adolc_memory.data() + i_memory; adolc_pattern[i][0] = n_nonzero[i]; pattern.begin(i); j = pattern.next_element(); k = 1; while(j != pattern.end() ) { adolc_pattern[i][k++] = j; j = pattern.next_element(); } CPPAD_ASSERT_UNKNOWN( k == 1 + n_nonzero[i] ); i_memory += k; } CPPAD_ASSERT_UNKNOWN( i_memory == m + n_nonzero_total ); // Must use an external routine for this part of the calculation because // ColPack/ColPackHeaders.h has as 'using namespace std' at global level. cppad_colpack_symmetric(color, m, adolc_pattern); // determine which sparsity entries need to be reflected size_t i1, i2, j1, j2, k1, k2; for(k1 = 0; k1 < row.size(); k1++) { i1 = row[k1]; j1 = col[k1]; bool reflect = false; for(i2 = 0; i2 < m; i2++) if( (i1 != i2) & (color[i1]==color[i2]) ) { for(k2 = 1; k2 <= adolc_pattern[i2][0]; k2++) { j2 = adolc_pattern[i2][k2]; reflect |= (j1 == j2); } } if( reflect ) { row[k1] = j1; col[k1] = i1; } } return; # endif // CPPAD_HAS_COLPACK } # endif TMB/inst/include/cppad/local/for_two.hpp0000644000176200001440000001476614536067013017670 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FOR_TWO_INCLUDED # define CPPAD_FOR_TWO_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ForTwo$$ $spell ddy typename Taylor const $$ $index partial, second order driver$$ $index second, order partial driver$$ $index driver, second order partial$$ $index easy, partial$$ $index driver, easy partial$$ $index partial, easy$$ $section Forward Mode Second Partial Derivative Driver$$ $head Syntax$$ $icode%ddy% = %f%.ForTwo(%x%, %j%, %k%)%$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. The syntax above sets $latex \[ ddy [ i * p + \ell ] = \DD{ F_i }{ x_{j[ \ell ]} }{ x_{k[ \ell ]} } (x) \] $$ for $latex i = 0 , \ldots , m-1$$ and $latex \ell = 0 , \ldots , p$$, where $latex p$$ is the size of the vectors $icode j$$ and $icode k$$. $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/ForTwo Uses Forward/ForTwo/ForTwo Uses Forward/$$ below). $head x$$ The argument $icode x$$ has prototype $codei% const %VectorBase% &%x% %$$ (see $cref/VectorBase/ForTwo/VectorBase/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies that point at which to evaluate the partial derivatives listed above. $head j$$ The argument $icode j$$ has prototype $codei% const %VectorSize_t% &%j% %$$ (see $cref/VectorSize_t/ForTwo/VectorSize_t/$$ below) We use $icode p$$ to denote the size of the vector $icode j$$. All of the indices in $icode j$$ must be less than $icode n$$; i.e., for $latex \ell = 0 , \ldots , p-1$$, $latex j[ \ell ] < n$$. $head k$$ The argument $icode k$$ has prototype $codei% const %VectorSize_t% &%k% %$$ (see $cref/VectorSize_t/ForTwo/VectorSize_t/$$ below) and its size must be equal to $icode p$$, the size of the vector $icode j$$. All of the indices in $icode k$$ must be less than $icode n$$; i.e., for $latex \ell = 0 , \ldots , p-1$$, $latex k[ \ell ] < n$$. $head ddy$$ The result $icode ddy$$ has prototype $codei% %VectorBase% %ddy% %$$ (see $cref/VectorBase/ForTwo/VectorBase/$$ below) and its size is $latex m * p$$. It contains the requested partial derivatives; to be specific, for $latex i = 0 , \ldots , m - 1 $$ and $latex \ell = 0 , \ldots , p - 1$$ $latex \[ ddy [ i * p + \ell ] = \DD{ F_i }{ x_{j[ \ell ]} }{ x_{k[ \ell ]} } (x) \] $$ $head VectorBase$$ The type $icode VectorBase$$ must be a $cref SimpleVector$$ class with $cref/elements of type Base/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head VectorSize_t$$ The type $icode VectorSize_t$$ must be a $cref SimpleVector$$ class with $cref/elements of type size_t/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head ForTwo Uses Forward$$ After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After a call to $code ForTwo$$, the zero order Taylor coefficients correspond to $icode%f%.Forward(0, %x%)%$$ and the other coefficients are unspecified. $head Examples$$ $children% example/for_two.cpp %$$ The routine $cref/ForTwo/for_two.cpp/$$ is both an example and test. It returns $code true$$, if it succeeds and $code false$$ otherwise. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template template VectorBase ADFun::ForTwo( const VectorBase &x, const VectorSize_t &j, const VectorSize_t &k) { size_t i; size_t j1; size_t k1; size_t l; size_t n = Domain(); size_t m = Range(); size_t p = j.size(); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector(); // check VectorSize_t is Simple Vector class with size_t elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( x.size() == n, "ForTwo: Length of x not equal domain dimension for f." ); CPPAD_ASSERT_KNOWN( j.size() == k.size(), "ForTwo: Lenght of the j and k vectors are not equal." ); // point at which we are evaluating the second partials Forward(0, x); // dimension the return value VectorBase ddy(m * p); // allocate memory to hold all possible diagonal Taylor coefficients // (for large sparse cases, this is not efficient) VectorBase D(m * n); // boolean flag for which diagonal coefficients are computed CppAD::vector c(n); for(j1 = 0; j1 < n; j1++) c[j1] = false; // direction vector in argument space VectorBase dx(n); for(j1 = 0; j1 < n; j1++) dx[j1] = Base(0); // result vector in range space VectorBase dy(m); // compute the diagonal coefficients that are needed for(l = 0; l < p; l++) { j1 = j[l]; k1 = k[l]; CPPAD_ASSERT_KNOWN( j1 < n, "ForTwo: an element of j not less than domain dimension for f." ); CPPAD_ASSERT_KNOWN( k1 < n, "ForTwo: an element of k not less than domain dimension for f." ); size_t count = 2; while(count) { count--; if( ! c[j1] ) { // diagonal term in j1 direction c[j1] = true; dx[j1] = Base(1); Forward(1, dx); dx[j1] = Base(0); dy = Forward(2, dx); for(i = 0; i < m; i++) D[i * n + j1 ] = dy[i]; } j1 = k1; } } // compute all the requested cross partials for(l = 0; l < p; l++) { j1 = j[l]; k1 = k[l]; if( j1 == k1 ) { for(i = 0; i < m; i++) ddy[i * p + l] = Base(2) * D[i * n + j1]; } else { // cross term in j1 and k1 directions dx[j1] = Base(1); dx[k1] = Base(1); Forward(1, dx); dx[j1] = Base(0); dx[k1] = Base(0); dy = Forward(2, dx); // place result in return value for(i = 0; i < m; i++) ddy[i * p + l] = dy[i] - D[i*n+j1] - D[i*n+k1]; } } return ddy; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/sparse_set.hpp0000644000176200001440000002500014536067013020340 0ustar liggesusers// $Id$ # ifndef CPPAD_SPARSE_SET_INCLUDED # define CPPAD_SPARSE_SET_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sparse_set.hpp Vector of sets of positive integers stored as std::set. */ /*! Vector of sets of positive integers, each set stored as a standard set. */ class sparse_set { private: /// type used for each set in the vector sets typedef std::set Set; /// Number of sets that we are representing /// (set by constructor and resize). size_t n_set_; /// Possible elements in each set are 0, 1, ..., end_ - 1 /// (set by constructor and resize). size_t end_; /// The vector of sets CppAD::vector data_; /// index for which we were retrieving next_element /// (use n_set_ if no such index exists). size_t next_index_; /// Next element that we will return using next_element /// (use end_ for no such element exists; i.e., past end of the set). Set::iterator next_element_; public: // ----------------------------------------------------------------- /*! Default constructor (no sets) */ sparse_set(void) : n_set_(0) , end_(0) , next_index_(0) { } // ----------------------------------------------------------------- /*! Make use of copy constructor an error \param v vector that we are attempting to make a copy of. */ sparse_set(const sparse_set& v) { // Error: // Probably a sparse_set argument has been passed by value CPPAD_ASSERT_UNKNOWN(false); } // ----------------------------------------------------------------- /*! Destructor */ ~sparse_set(void) { } // ----------------------------------------------------------------- /*! Change number of sets, set end, and initialize all sets as empty If \c n_set_in is zero, any memory currently allocated for this object is freed. Otherwise, new memory may be allocated for the sets (if needed). \param n_set_in is the number of sets in this vector of sets. \param end_in is the maximum element plus one (the minimum element is 0). */ void resize(size_t n_set_in, size_t end_in) { n_set_ = n_set_in; end_ = end_in; if( n_set_ == 0 ) { // free all memory connected with data_ data_.clear(); return; } // now start a new vector with empty sets data_.resize(n_set_); // value that signfies past end of list next_index_ = n_set_; } // ----------------------------------------------------------------- /*! Add one element to a set. \param index is the index for this set in the vector of sets. \param element is the element we are adding to the set. \par Checked Assertions \li index < n_set_ \li element < end_ */ void add_element(size_t index, size_t element) { // This routine should use the std::insert operator // that cashes the iterator of previous insertion for when // insertions occur in order. We should speed test that this // actually makes things faster. CPPAD_ASSERT_UNKNOWN( index < n_set_ ); CPPAD_ASSERT_UNKNOWN( element < end_ ); data_[ index ].insert( element ); } // ----------------------------------------------------------------- /*! Is an element of a set. \param index is the index for this set in the vector of sets. \param element is the element we are adding to the set. \par Checked Assertions \li index < n_set_ \li element < end_ */ bool is_element(size_t index, size_t element) { // This routine should use the std::insert operator // that cashes the iterator of previous insertion for when // insertions occur in order. We should speed test that this // actually makes things faster. CPPAD_ASSERT_UNKNOWN( index < n_set_ ); CPPAD_ASSERT_UNKNOWN( element < end_ ); std::set::iterator itr = data_[ index ].find( element ); return itr != data_[index].end(); } // ----------------------------------------------------------------- /*! Begin retrieving elements from one of the sets. \param index is the index for the set that is going to be retrieved. The elements of the set are retrieved in increasing order. \par Checked Assertions \li index < n_set_ */ void begin(size_t index) { // initialize element to search for in this set CPPAD_ASSERT_UNKNOWN( index < n_set_ ); next_index_ = index; next_element_ = data_[index].begin(); return; } // ----------------------------------------------------------------- /*! Get the next element from the current retrieval set. \return is the next element in the set with index specified by the previous call to \c begin. If no such element exists, \c this->end() is returned. */ size_t next_element(void) { if( next_element_ == data_[next_index_].end() ) return end_; return *next_element_++; } // ----------------------------------------------------------------- /*! Assign the empty set to one of the sets. \param target is the index of the set we are setting to the empty set. \par Checked Assertions \li target < n_set_ */ void clear(size_t target) { CPPAD_ASSERT_UNKNOWN( target < n_set_ ); data_[target].clear(); } // ----------------------------------------------------------------- /*! Assign one set equal to another set. \param this_target is the index (in this \c sparse_set object) of the set being assinged. \param other_value is the index (in the other \c sparse_set object) of the that we are using as the value to assign to the target set. \param other is the other \c sparse_set object (which may be the same as this \c sparse_set object). \par Checked Assertions \li this_target < n_set_ \li other_value < other.n_set_ */ void assignment( size_t this_target , size_t other_value , const sparse_set& other ) { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ ); CPPAD_ASSERT_UNKNOWN( other_value < other.n_set_ ); data_[this_target] = other.data_[other_value]; } // ----------------------------------------------------------------- /*! Assign a set equal to the union of two other sets. \param this_target is the index (in this \c sparse_set object) of the set being assinged. \param this_left is the index (in this \c sparse_set object) of the left operand for the union operation. It is OK for \a this_target and \a this_left to be the same value. \param other_right is the index (in the other \c sparse_set object) of the right operand for the union operation. It is OK for \a this_target and \a other_right to be the same value. \param other is the other \c sparse_set object (which may be the same as this \c sparse_set object). \par Checked Assertions \li this_target < n_set_ \li this_left < n_set_ \li other_right < other.n_set_ */ void binary_union( size_t this_target , size_t this_left , size_t other_right , const sparse_set& other ) { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ ); CPPAD_ASSERT_UNKNOWN( this_left < n_set_ ); CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_ ); // use a temporary set for holding results // (in case target set is same as one of the other sets) Set temp; std::set_union( data_[this_left].begin() , data_[this_left].end() , other.data_[other_right].begin() , other.data_[other_right].end() , std::inserter(temp, temp.begin()) ); // move results to the target set with out copying elements data_[this_target].swap(temp); } // ----------------------------------------------------------------- /*! Sum over all sets of the number of elements /return The the total number of elements */ size_t number_elements(void) const { size_t i, count; count = 0; for(i = 0; i < n_set_; i++) count += data_[i].size(); return count; } // ----------------------------------------------------------------- /*! Fetch n_set for vector of sets object. \return Number of from sets for this vector of sets object */ size_t n_set(void) const { return n_set_; } // ----------------------------------------------------------------- /*! Fetch end for this vector of sets object. \return is the maximum element value plus one (the minimum element value is 0). */ size_t end(void) const { return end_; } }; /*! Copy a user vector of sets sparsity pattern to an internal sparse_set object. \tparam VectorSet is a simple vector with elements of type \c std::set. \param internal The input value of sparisty does not matter. Upon return it contains the same sparsity pattern as \c user (or the transposed sparsity pattern). \param user sparsity pattern that we are placing \c internal. \param n_row number of rows in the sparsity pattern in \c user (range dimension). \param n_col number of columns in the sparsity pattern in \c user (domain dimension). \param transpose if true, the sparsity pattern in \c internal is the transpose of the one in \c user. Otherwise it is the same sparsity pattern. */ template void sparsity_user2internal( sparse_set& internal , const VectorSet& user , size_t n_row , size_t n_col , bool transpose ) { CPPAD_ASSERT_UNKNOWN( n_row == size_t(user.size()) ); CPPAD_ASSERT_KNOWN( size_t( user.size() ) == n_row, "Size of this vector of sets sparsity pattern is not equal " "the range dimension for the corresponding function." ); size_t i, j; std::set::const_iterator itr; // transposed pattern case if( transpose ) { internal.resize(n_col, n_row); for(i = 0; i < n_row; i++) { itr = user[i].begin(); while(itr != user[i].end()) { j = *itr++; CPPAD_ASSERT_UNKNOWN( j < n_col ); internal.add_element(j, i); } } return; } // same pattern case internal.resize(n_row, n_col); for(i = 0; i < n_row; i++) { itr = user[i].begin(); while(itr != user[i].end()) { j = *itr++; CPPAD_ASSERT_UNKNOWN( j < n_col ); internal.add_element(i, j); } } return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/rev_sparse_jac.hpp0000644000176200001440000004162514536067013021171 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_REV_SPARSE_JAC_INCLUDED # define CPPAD_REV_SPARSE_JAC_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin RevSparseJac$$ $spell optimizer nz CondExpRel std VecAD var Jacobian Jac const Bool Dep proportional $$ $section Jacobian Sparsity Pattern: Reverse Mode$$ $index RevSparseJac$$ $index reverse, sparse Jacobian$$ $index sparse, reverse Jacobian$$ $index pattern, reverse Jacobian$$ $head Syntax$$ $icode%s% = %f%.RevSparseJac(%q%, %r%) %$$ $icode%s% = %f%.RevSparseJac(%q%, %r%, %transpose%)%$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. For a fixed matrix $latex R \in B^{q \times m}$$, the Jacobian of $latex R * F( x )$$ with respect to $latex x$$ is $latex \[ S(x) = R * F^{(1)} ( x ) \] $$ Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$, $code RevSparseJac$$ returns a sparsity pattern for the $latex S(x)$$. $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ $head x$$ the sparsity pattern is valid for all values of the independent variables in $latex x \in B^n$$ (even if it has $cref CondExp$$ or $cref VecAD$$ operations). $head q$$ The argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of rows in $latex R \in B^{q \times m}$$ and the Jacobian $latex S(x) \in B^{q \times n}$$. $head transpose$$ The argument $icode transpose$$ has prototype $codei% bool %transpose% %$$ The default value $code false$$ is used when $icode transpose$$ is not present. $head nz_compare$$ The argument $icode nz_compare$$ has prototype $codei% bool %nz_compare% %$$ If $icode nz_compare$$ is true, the derivatives with respect to left and right of the $cref CondExp$$ below are considered to be non-zero: $codei% %CondExp%Rel%(%left%, %right%, %if_true%, %if_false%) %$$ This is used by the $cref/optimizer/optimize/$$ with $cref checkpoint$$ functions to obtain the correct dependency relations. The default value $icode%nz_compare% = false%$$ is used when $icode nz_compare$$ is not present. $head r$$ The argument $icode s$$ has prototype $codei% const %VectorSet%& %r% %$$ see $cref/VectorSet/RevSparseJac/VectorSet/$$ below. $subhead transpose false$$ If $icode r$$ has elements of type $code bool$$, its size is $latex q * m$$. If it has elements of type $code std::set$$, its size is $icode q$$ and all its set elements are between zero and $latex m - 1$$. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex R \in B^{q \times m}$$. $subhead transpose true$$ If $icode r$$ has elements of type $code bool$$, its size is $latex m * q$$. If it has elements of type $code std::set$$, its size is $icode m$$ and all its set elements are between zero and $latex q - 1$$. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex R^\R{T} \in B^{m \times q}$$. $head s$$ The return value $icode s$$ has prototype $codei% %VectorSet% %s% %$$ see $cref/VectorSet/RevSparseJac/VectorSet/$$ below. $subhead transpose false$$ If it has elements of type $code bool$$, its size is $latex q * n$$. If it has elements of type $code std::set$$, its size is $icode q$$ and all its set elements are between zero and $latex n - 1$$. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex S(x) \in {q \times n}$$. $subhead transpose true$$ If it has elements of type $code bool$$, its size is $latex n * q$$. If it has elements of type $code std::set$$, its size is $icode n$$ and all its set elements are between zero and $latex q - 1$$. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex S(x)^\R{T} \in {n \times q}$$. $head VectorSet$$ The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code bool$$ or $code std::set$$; see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion of the difference. $head Entire Sparsity Pattern$$ Suppose that $latex q = m$$ and $latex R$$ is the $latex m \times m$$ identity matrix. In this case, the corresponding value for $icode s$$ is a sparsity pattern for the Jacobian $latex S(x) = F^{(1)} ( x )$$. $head Example$$ $children% example/rev_sparse_jac.cpp %$$ The file $cref rev_sparse_jac.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file rev_sparse_jac.hpp Reverse mode Jacobian sparsity patterns. */ // ------------------------------------------------------------------------- /*! Calculate Jacobian vector of bools sparsity patterns using reverse mode. The C++ source code corresponding to this operation is \verbatim s = f.RevSparseJac(q, r) \endverbatim \tparam Base is the base type for this recording. \tparam VectorSet is a simple vector class with elements of type \c bool. \param transpose are the sparsity patterns transposed. \param nz_compare Are the derivatives with respect to left and right of the expression below considered to be non-zero: \code CondExpRel(left, right, if_true, if_false) \endcode This is used by the optimizer to obtain the correct dependency relations. \param q is the number of rows in the matrix \f$ R \f$. \param r is a sparsity pattern for the matrix \f$ R \f$. \param s the input value of \a s must be a vector with size p*n where \c n is the number of independent variables corresponding to the operation sequence stored in \a play. The input value of the components of \c s does not matter. On output, \a s is the sparsity pattern for the matrix \f[ S(x) = R * F^{(1)} (x) \f] where \f$ F \f$ is the function corresponding to the operation sequence and \a x is any argument value. \param total_num_var is the total number of variable in this recording. \param dep_taddr maps dependendent variable index to the corresponding variable in the tape. \param ind_taddr maps independent variable index to the corresponding variable in the tape. \param play is the recording that defines the function we are computing the sparsity pattern for. */ template void RevSparseJacBool( bool transpose , bool nz_compare , size_t q , const VectorSet& r , VectorSet& s , size_t total_num_var , CppAD::vector& dep_taddr , CppAD::vector& ind_taddr , CppAD::player& play ) { // temporary indices size_t i, j; // check VectorSet is Simple Vector class with bool elements CheckSimpleVector(); // range and domain dimensions for F size_t m = dep_taddr.size(); size_t n = ind_taddr.size(); CPPAD_ASSERT_KNOWN( q > 0, "RevSparseJac: q is not greater than zero" ); CPPAD_ASSERT_KNOWN( size_t(r.size()) == q * m, "RevSparseJac: size of r is not equal to\n" "q times range dimension for ADFun object." ); // vector of sets that will hold the results sparse_pack var_sparsity; var_sparsity.resize(total_num_var, q); // The sparsity pattern corresponding to the dependent variables for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr[i] < total_num_var ); if( transpose ) { for(j = 0; j < q; j++) if( r[ j * m + i ] ) var_sparsity.add_element( dep_taddr[i], j ); } else { for(j = 0; j < q; j++) if( r[ i * q + j ] ) var_sparsity.add_element( dep_taddr[i], j ); } } // evaluate the sparsity patterns RevJacSweep( nz_compare, n, total_num_var, &play, var_sparsity ); // return values corresponding to dependent variables CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q * n ); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr[j] == (j+1) ); // ind_taddr[j] is operator taddr for j-th independent variable CPPAD_ASSERT_UNKNOWN( play.GetOp( ind_taddr[j] ) == InvOp ); // extract the result from var_sparsity if( transpose ) { for(i = 0; i < q; i++) s[ j * q + i ] = false; } else { for(i = 0; i < q; i++) s[ i * n + j ] = false; } CPPAD_ASSERT_UNKNOWN( var_sparsity.end() == q ); var_sparsity.begin(j+1); i = var_sparsity.next_element(); while( i < q ) { if( transpose ) s[ j * q + i ] = true; else s[ i * n + j ] = true; i = var_sparsity.next_element(); } } } /*! Calculate Jacobian vector of sets sparsity patterns using reverse mode. The C++ source code corresponding to this operation is \verbatim s = f.RevSparseJac(q, r) \endverbatim \tparam Base see \c RevSparseJacBool. \tparam VectorSet is a simple vector class with elements of type \c std::set. \param transpose see \c RevSparseJacBool. \param nz_compare see \c RevSparseJacBool. \param q see \c RevSparseJacBool. \param r see \c RevSparseJacBool. \param s see \c RevSparseJacBool. \param total_num_var see \c RevSparseJacBool. \param dep_taddr see \c RevSparseJacBool. \param ind_taddr see \c RevSparseJacBool. \param play see \c RevSparseJacBool. */ template void RevSparseJacSet( bool transpose , bool nz_compare , size_t q , const VectorSet& r , VectorSet& s , size_t total_num_var , CppAD::vector& dep_taddr , CppAD::vector& ind_taddr , CppAD::player& play ) { // temporary indices size_t i, j; std::set::const_iterator itr; // check VectorSet is Simple Vector class with sets for elements CheckSimpleVector, VectorSet>( one_element_std_set(), two_element_std_set() ); // domain dimensions for F size_t n = ind_taddr.size(); size_t m = dep_taddr.size(); CPPAD_ASSERT_KNOWN( q > 0, "RevSparseJac: q is not greater than zero" ); CPPAD_ASSERT_KNOWN( size_t(r.size()) == q || transpose, "RevSparseJac: size of r is not equal to q and transpose is false." ); CPPAD_ASSERT_KNOWN( size_t(r.size()) == m || ! transpose, "RevSparseJac: size of r is not equal to m and transpose is true." ); // vector of lists that will hold the results CPPAD_INTERNAL_SPARSE_SET var_sparsity; var_sparsity.resize(total_num_var, q); // The sparsity pattern corresponding to the dependent variables if( transpose ) { for(i = 0; i < m; i++) { itr = r[i].begin(); while(itr != r[i].end()) { j = *itr++; CPPAD_ASSERT_KNOWN( j < q, "RevSparseJac: transpose is true and element of the set\n" "r[i] has value greater than or equal q." ); CPPAD_ASSERT_UNKNOWN( dep_taddr[i] < total_num_var ); var_sparsity.add_element( dep_taddr[i], j ); } } } else { for(i = 0; i < q; i++) { itr = r[i].begin(); while(itr != r[i].end()) { j = *itr++; CPPAD_ASSERT_KNOWN( j < m, "RevSparseJac: transpose is false and element of the set\n" "r[i] has value greater than or equal range dimension." ); CPPAD_ASSERT_UNKNOWN( dep_taddr[j] < total_num_var ); var_sparsity.add_element( dep_taddr[j], i ); } } } // evaluate the sparsity patterns RevJacSweep( nz_compare, n, total_num_var, &play, var_sparsity ); // return values corresponding to dependent variables CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q || transpose ); CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == n || ! transpose ); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr[j] == (j+1) ); // ind_taddr[j] is operator taddr for j-th independent variable CPPAD_ASSERT_UNKNOWN( play.GetOp( ind_taddr[j] ) == InvOp ); CPPAD_ASSERT_UNKNOWN( var_sparsity.end() == q ); var_sparsity.begin(j+1); i = var_sparsity.next_element(); while( i < q ) { if( transpose ) s[j].insert(i); else s[i].insert(j); i = var_sparsity.next_element(); } } } // -------------------------------------------------------------------------- /*! Private helper function for \c RevSparseJac(q, r, transpose). All of the description in the public member function \c RevSparseJac(q, r, transpose) apply. \param set_type is a \c bool value. This argument is used to dispatch to the proper source code depending on the value of \c VectorSet::value_type. \param transpose See \c RevSparseJac(q, r, transpose, nz_compare) \param nz_compare See \c RevSparseJac(q, r, transpose, nz_compare) \param q See \c RevSparseJac(q, r, transpose, nz_compare) \param r See \c RevSparseJac(q, r, transpose, nz_compare) \param s is the return value for the corresponding call to RevSparseJac(q, r, transpose). */ template template void ADFun::RevSparseJacCase( bool set_type , bool transpose , bool nz_compare , size_t q , const VectorSet& r , VectorSet& s ) { size_t n = Domain(); // dimension of the result vector s.resize( q * n ); // store results in s RevSparseJacBool( transpose , nz_compare , q , r , s , num_var_tape_ , dep_taddr_ , ind_taddr_ , play_ ); } /*! Private helper function for \c RevSparseJac(q, r, transpose). All of the description in the public member function \c RevSparseJac(q, r, transpose) apply. \param set_type is a \c std::set object. This argument is used to dispatch to the proper source code depending on the value of \c VectorSet::value_type. \param transpose See \c RevSparseJac(q, r, transpose, nz_compare) \param nz_compare See \c RevSparseJac(q, r, transpose, nz_compare) \param q See \c RevSparseJac(q, r, transpose, nz_compare) \param r See \c RevSparseJac(q, r, transpose, nz_compare) \param s is the return value for the corresponding call to RevSparseJac(q, r, transpose) */ template template void ADFun::RevSparseJacCase( const std::set& set_type , bool transpose , bool nz_compare , size_t q , const VectorSet& r , VectorSet& s ) { // dimension of the result vector if( transpose ) s.resize( Domain() ); else s.resize( q ); // store results in r RevSparseJacSet( transpose , nz_compare , q , r , s , num_var_tape_ , dep_taddr_ , ind_taddr_ , play_ ); } // -------------------------------------------------------------------------- /*! User API for Jacobian sparsity patterns using reverse mode. The C++ source code corresponding to this operation is \verbatim s = f.RevSparseJac(q, r, transpose, nz_compare) \endverbatim \tparam Base is the base type for this recording. \tparam VectorSet is a simple vector with elements of type \c bool. or \c std::set. \param q is the number of rows in the matrix \f$ R \f$. \param r is a sparsity pattern for the matrix \f$ R \f$. \param transpose are the sparsity patterns for \f$ R \f$ and \f$ S(x) \f$ transposed. \param nz_compare Are the derivatives with respect to left and right of the expression below considered to be non-zero: \code CondExpRel(left, right, if_true, if_false) \endcode This is used by the optimizer to obtain the correct dependency relations. \return If \c transpose is false (true), the return value is a sparsity pattern for \f$ S(x) \f$ (\f$ S(x)^T \f$) where \f[ S(x) = R * F^{(1)} (x) \f] and \f$ F \f$ is the function corresponding to the operation sequence and \a x is any argument value. If \c VectorSet::value_type is \c bool, the return value has size \f$ q * n \f$ ( \f$ n * q \f$). If \c VectorSet::value_type is \c std::set, the return value has size \f$ q \f$ ( \f$ n \f$) and with all its elements between zero and \f$ n - 1 \f$ (\f$ q - 1 \f$). */ template template VectorSet ADFun::RevSparseJac( size_t q , const VectorSet& r , bool transpose , bool nz_compare ) { VectorSet s; typedef typename VectorSet::value_type Set_type; RevSparseJacCase( Set_type() , transpose , nz_compare , q , r , s ); return s; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/bool_valued.hpp0000644000176200001440000000237114536067013020471 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BOOL_VALUED_INCLUDED # define CPPAD_BOOL_VALUED_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-06 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin BoolValued$$ $spell Bool $$ $index operation, AD Bool valued$$ $index function, AD Bool valued$$ $section Bool Valued Operations and Functions with AD Arguments$$ $children% cppad/local/compare.hpp% cppad/local/near_equal_ext.hpp% cppad/local/bool_fun.hpp% cppad/local/par_var.hpp% cppad/local/equal_op_seq.hpp %$$ $table $rref Compare$$ $rref NearEqualExt$$ $rref BoolFun$$ $rref ParVar$$ $rref EqualOpSeq$$ $tend $end */ # include # include # include # include # include # endif TMB/inst/include/cppad/local/std_set.hpp0000644000176200001440000000261314536067013017642 0ustar liggesusers// $Id$ # ifndef CPPAD_STD_SET_INCLUDED # define CPPAD_STD_SET_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file std_set.hpp Two constant standard sets (currently used for concept checking). */ /*! A standard set with one element. */ template const std::set& one_element_std_set(void) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static std::set one; if( one.empty() ) one.insert(1); return one; } /*! A standard set with a two elements. */ template const std::set& two_element_std_set(void) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static std::set two; if( two.empty() ) { two.insert(1); two.insert(2); } return two; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/capacity_order.hpp0000644000176200001440000001653614536067013021176 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_CAPACITY_ORDER_INCLUDED # define CPPAD_CAPACITY_ORDER_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin capacity_order$$ $spell var taylor_ xq yq $$ $index Forward, capacity$$ $index capacity_order$$ $index capacity, Forward$$ $index control, memory$$ $index memory, control$$ $section Controlling Taylor Coefficients Memory Allocation$$ $head Syntax$$ $icode%f%.capacity_order(%c%)%$$ $subhead See Also$$ $cref seq_property$$ $head Purpose$$ The Taylor coefficients calculated by $cref Forward$$ mode calculations are retained in an $cref ADFun$$ object for subsequent use during $cref Reverse$$ mode and higher order Forward mode calculations. For example, a call to $cref/Forward/forward_order/$$ with the syntax $codei% %yq% = %f%.Forward(%q%, %xq%) %$$ where $icode%q% > 0%$$ and $code%xq%.size() == %f%.Domain()%$$, uses the lower order Taylor coefficients and computes the $th q$$ order Taylor coefficients for all the variables in the operation sequence corresponding to $icode f$$. The $code capacity_order$$ operation allows you to control that amount of memory that is retained by an AD function object (to hold $code Forward$$ results for subsequent calculations). $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ $head c$$ The argument $icode c$$ has prototype $codei% size_t %c% %$$ It specifies the number of Taylor coefficient orders that are allocated in the AD operation sequence corresponding to $icode f$$. $subhead Pre-Allocating Memory$$ If you plan to make calls to $code Forward$$ with the maximum value of $icode q$$ equal to $icode Q$$, it should be faster to pre-allocate memory for these calls using $codei% %f%.capacity_order(%c%) %$$ with $icode c$$ equal to $latex Q + 1$$. If you do no do this, $code Forward$$ will automatically allocate memory and will copy the results to a larger buffer, when necessary. $pre $$ Note that each call to $cref Dependent$$ frees the old memory connected to the function object and sets the corresponding taylor capacity to zero. $subhead Freeing Memory$$ If you no longer need the Taylor coefficients of order $icode q$$ and higher (that are stored in $icode f$$), you can reduce the memory allocated to $icode f$$ using $codei% %f%.capacity_order(%c%) %$$ with $icode c$$ equal to $icode q$$. Note that, if $cref ta_hold_memory$$ is true, this memory is not actually returned to the system, but rather held for future use by the same thread. $head Original State$$ If $icode f$$ is $cref/constructed/FunConstruct/$$ with the syntax $codei% ADFun<%Base%> %f%(%x%, %y%) %$$, there is an implicit call to $cref forward_zero$$ with $icode xq$$ equal to the value of the $cref/independent variables/glossary/Tape/Independent Variable/$$ when the AD operation sequence was recorded. This corresponds to $icode%c% == 1%$$. $children% example/capacity_order.cpp %$$ $head Example$$ The file $cref capacity_order.cpp$$ contains an example and test of these operations. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file capacity_order.hpp Control of number of orders allocated. \} */ /*! Control of number of orders and directions allocated. \tparam Base The type used during the forward mode computations; i.e., the corresponding recording of operations used the type AD. \param c is the number of orders to allocate memory for. If c == 0 then \c r must also be zero. In this case num_order_taylor_, cap_order_taylor_, and num_direction_taylor_ are all set to zero. In addition, taylor_.free() is called. \param r is the number of directions to allocate memory for. If c == 1 then \c r must also be one. In all cases, it must hold that r == num_direction_taylor_ || num_order_taylor <= 1 Upon return, num_direction_taylor_ is equal to r. \par num_order_taylor_ The output value of num_order_taylor_ is the mininumum of its input value and c. This minimum is the number of orders that are copied to the new taylor coefficient buffer. \par num_direction_taylor_ The output value of num_direction_taylor_ is equal to \c r. */ template void ADFun::capacity_order(size_t c, size_t r) { // temporary indices size_t i, k, ell; if( (c == cap_order_taylor_) & (r == num_direction_taylor_) ) return; if( c == 0 ) { CPPAD_ASSERT_UNKNOWN( r == 0 ); taylor_.free(); num_order_taylor_ = 0; cap_order_taylor_ = 0; num_direction_taylor_ = r; return; } CPPAD_ASSERT_UNKNOWN(r==num_direction_taylor_ || num_order_taylor_<=1); // Allocate new taylor with requested number of orders and directions size_t new_len = ( (c-1)*r + 1 ) * num_var_tape_; pod_vector new_taylor; new_taylor.extend(new_len); // number of orders to copy size_t p = std::min(num_order_taylor_, c); if( p > 0 ) { // old order capacity size_t C = cap_order_taylor_; // old number of directions size_t R = num_direction_taylor_; // copy the old data into the new matrix CPPAD_ASSERT_UNKNOWN( p == 1 || r == R ); for(i = 0; i < num_var_tape_; i++) { // copy zero order size_t old_index = ((C-1) * R + 1) * i + 0; size_t new_index = ((c-1) * r + 1) * i + 0; new_taylor[ new_index ] = taylor_[ old_index ]; // copy higher orders for(k = 1; k < p; k++) { for(ell = 0; ell < R; ell++) { old_index = ((C-1) * R + 1) * i + (k-1) * R + ell + 1; new_index = ((c-1) * r + 1) * i + (k-1) * r + ell + 1; new_taylor[ new_index ] = taylor_[ old_index ]; } } } } // replace taylor_ by new_taylor taylor_.swap(new_taylor); cap_order_taylor_ = c; num_order_taylor_ = p; num_direction_taylor_ = r; // note that the destructor for new_taylor will free the old taylor memory return; } /*! User API control of number of orders allocated. \tparam Base The type used during the forward mode computations; i.e., the corresponding recording of operations used the type AD. \param c is the number of orders to allocate memory for. If c == 0, num_order_taylor_, cap_order_taylor_, and num_direction_taylor_ are all set to zero. In addition, taylor_.free() is called. \par num_order_taylor_ The output value of num_order_taylor_ is the mininumum of its input value and c. This minimum is the number of orders that are copied to the new taylor coefficient buffer. \par num_direction_taylor_ If \c is zero (one), \c num_direction_taylor_ is set to zero (one). Otherwise, if \c num_direction_taylor_ is zero, it is set to one. Othwerwise, \c num_direction_taylor_ is not modified. */ template void ADFun::capacity_order(size_t c) { size_t r; if( (c == 0) | (c == 1) ) { r = c; capacity_order(c, r); return; } r = num_direction_taylor_; if( r == 0 ) r = 1; capacity_order(c, r); return; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/cond_exp.hpp0000644000176200001440000002256414536067013020003 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_COND_EXP_INCLUDED # define CPPAD_COND_EXP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin CondExp$$ $spell Atan2 CondExp Taylor std Cpp namespace inline const abs Rel bool Lt Le Eq Ge Gt $$ $index conditional, expression$$ $index expression, conditional$$ $index assign, conditional$$ $section AD Conditional Expressions$$ $head Syntax$$ $icode%result% = CondExp%Rel%(%left%, %right%, %if_true%, %if_false%)%$$ $head Purpose$$ Record, as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$, the conditional result $codei% if( %left% %Cop% %right% ) %result% = %if_true% else %result% = %if_false% %$$ The relational $icode Rel$$ and comparison operator $icode Cop$$ above have the following correspondence: $codei% %Rel% Lt Le Eq Ge Gt %Cop% < <= == >= > %$$ If $icode f$$ is the $cref ADFun$$ object corresponding to the AD operation sequence, the assignment choice for $icode result$$ in an AD conditional expression is made each time $cref/f.Forward/Forward/$$ is used to evaluate the zero order Taylor coefficients with new values for the $cref/independent variables/glossary/Tape/Independent Variable/$$. This is in contrast to the $cref/AD comparison operators/Compare/$$ which are boolean valued and not included in the AD operation sequence. $head Rel$$ In the syntax above, the relation $icode Rel$$ represents one of the following two characters: $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, $code Gt$$. As in the table above, $icode Rel$$ determines which comparison operator $icode Cop$$ is used when comparing $icode left$$ and $icode right$$. $head Type$$ These functions are defined in the CppAD namespace for arguments of $icode Type$$ is $code float$$ , $code double$$, or any type of the form $codei%AD<%Base%>%$$. (Note that all four arguments must have the same type.) $head left$$ The argument $icode left$$ has prototype $codei% const %Type%& %left% %$$ It specifies the value for the left side of the comparison operator. $head right$$ The argument $icode right$$ has prototype $codei% const %Type%& %right% %$$ It specifies the value for the right side of the comparison operator. $head if_true$$ The argument $icode if_true$$ has prototype $codei% const %Type%& %if_true% %$$ It specifies the return value if the result of the comparison is true. $head if_false$$ The argument $icode if_false$$ has prototype $codei% const %Type%& %if_false% %$$ It specifies the return value if the result of the comparison is false. $head result$$ The $icode result$$ has prototype $codei% %Type%& %if_false% %$$ $head Optimize$$ The $cref optimize$$ method will optimize conditional expressions in the following way: During $cref/zero order forward mode/forward_zero/$$, once the value of the $icode left$$ and $icode right$$ have been determined, it is known if the true or false case is required. From this point on, values corresponding to the case that is not required are not computed. This optimization is done for the rest of zero order forward mode as well as forward and reverse derivatives calculations. There is one exception to this optimization; see $cref/wish list/WishList/Conditional Expressions/$$. $head Deprecate 2005-08-07$$ Previous versions of CppAD used $codei% CondExp(%flag%, %if_true%, %if_false%) %$$ for the same meaning as $codei% CondExpGt(%flag%, %Type%(0), %if_true%, %if_false%) %$$ Use of $code CondExp$$ is deprecated, but continues to be supported. $head Operation Sequence$$ This is an AD of $icode Base$$ $cref/atomic operation/glossary/Operation/Atomic/$$ and hence is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Example$$ $head Test$$ $children% example/cond_exp.cpp %$$ The file $cref cond_exp.cpp$$ contains an example and test of this function. It returns true if it succeeds and false otherwise. $head Atan2$$ The following implementation of the AD $cref atan2$$ function is a more complex example of using conditional expressions: $code $verbatim%cppad/local/atan2.hpp%0%BEGIN CondExp%// END CondExp%$$ $$ $end ------------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION AD CondExpOp( enum CompareOp cop , const AD &left , const AD &right , const AD &if_true , const AD &if_false ) { AD returnValue; CPPAD_ASSERT_UNKNOWN( Parameter(returnValue) ); // check first case where do not need to tape if( IdenticalPar(left) && IdenticalPar(right) ) { switch( cop ) { case CompareLt: if( left.value_ < right.value_ ) returnValue = if_true; else returnValue = if_false; break; case CompareLe: if( left.value_ <= right.value_ ) returnValue = if_true; else returnValue = if_false; break; case CompareEq: if( left.value_ == right.value_ ) returnValue = if_true; else returnValue = if_false; break; case CompareGe: if( left.value_ >= right.value_ ) returnValue = if_true; else returnValue = if_false; break; case CompareGt: if( left.value_ > right.value_ ) returnValue = if_true; else returnValue = if_false; break; default: CPPAD_ASSERT_UNKNOWN(0); returnValue = if_true; } return returnValue; } // must use CondExp incase Base is an AD type and recording returnValue.value_ = CondExpOp(cop, left.value_, right.value_, if_true.value_, if_false.value_); ADTape *tape = CPPAD_NULL; if( Variable(left) ) tape = left.tape_this(); if( Variable(right) ) tape = right.tape_this(); if( Variable(if_true) ) tape = if_true.tape_this(); if( Variable(if_false) ) tape = if_false.tape_this(); // add this operation to the tape if( tape != CPPAD_NULL ) tape->RecordCondExp(cop, returnValue, left, right, if_true, if_false); return returnValue; } // --- RecordCondExp(cop, returnValue, left, right, if_true, if_false) ----- /// All these operations are done in \c Rec_, so we should move this /// routine to recorder. template void ADTape::RecordCondExp( enum CompareOp cop , AD &returnValue , const AD &left , const AD &right , const AD &if_true , const AD &if_false ) { size_t ind0, ind1, ind2, ind3, ind4, ind5; size_t returnValue_taddr; // taddr_ of this variable CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); returnValue_taddr = Rec_.PutOp(CExpOp); // ind[0] = cop ind0 = addr_t( cop ); // ind[1] = base 2 representaion of the value // [Var(left), Var(right), Var(if_true), Var(if_false)] ind1 = 0; // Make sure returnValue is in the list of variables and set its taddr if( Parameter(returnValue) ) returnValue.make_variable(id_, returnValue_taddr ); else returnValue.taddr_ = returnValue_taddr; // ind[2] = left address if( Parameter(left) ) ind2 = Rec_.PutPar(left.value_); else { ind1 += 1; ind2 = left.taddr_; } // ind[3] = right address if( Parameter(right) ) ind3 = Rec_.PutPar(right.value_); else { ind1 += 2; ind3 = right.taddr_; } // ind[4] = if_true address if( Parameter(if_true) ) ind4 = Rec_.PutPar(if_true.value_); else { ind1 += 4; ind4 = if_true.taddr_; } // ind[5] = if_false address if( Parameter(if_false) ) ind5 = Rec_.PutPar(if_false.value_); else { ind1 += 8; ind5 = if_false.taddr_; } CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( ind1 > 0 ); Rec_.PutArg(ind0, ind1, ind2, ind3, ind4, ind5); // check that returnValue is a dependent variable CPPAD_ASSERT_UNKNOWN( Variable(returnValue) ); } // ------------ CondExpOp(left, right, if_true, if_false) ---------------- # define CPPAD_COND_EXP(Name) \ template \ CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION \ AD CondExp##Name( \ const AD &left , \ const AD &right , \ const AD &if_true , \ const AD &if_false ) \ { \ return CondExpOp(Compare##Name, \ left, right, if_true, if_false); \ } // AD CPPAD_COND_EXP(Lt) CPPAD_COND_EXP(Le) CPPAD_COND_EXP(Eq) CPPAD_COND_EXP(Ge) CPPAD_COND_EXP(Gt) template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION AD CondExp( const AD &flag , const AD &if_true , const AD &if_false ) { return CondExpOp(CompareGt, flag, AD(0), if_true, if_false); } # undef CPPAD_COND_EXP } // END CppAD namespace # endif TMB/inst/include/cppad/local/sparse_pack.hpp0000644000176200001440000002717514536067013020502 0ustar liggesusers// $Id$ # ifndef CPPAD_SPARSE_PACK_INCLUDED # define CPPAD_SPARSE_PACK_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sparse_pack.hpp Vector of sets of positive integers stored as a packed array of bools. */ /*! Vector of sets of postivie integers, each set stored as a packed boolean array. */ class sparse_pack { private: /// Type used to pack elements (should be the same as corresponding /// typedef in multiple_n_bit() in test_more/sparse_hacobian.cpp) typedef size_t Pack; /// Number of bits per Pack value static const size_t n_bit_ = std::numeric_limits::digits; /// Number of sets that we are representing /// (set by constructor and resize). size_t n_set_; /// Possible elements in each set are 0, 1, ..., end_ - 1 /// (set by constructor and resize). size_t end_; /// Number of \c Pack values necessary to represent \c end_ bits. /// (set by constructor and resize). size_t n_pack_; /// Data for all the sets. pod_vector data_; /// index for which we were retrieving next_element /// (use n_set_ if no such index exists). size_t next_index_; /// Next element to start search at /// (use end_ for no such element exists; i.e., past end of the set). size_t next_element_; public: // ----------------------------------------------------------------- /*! Default constructor (no sets) */ sparse_pack(void) : n_set_(0) , end_(0) , n_pack_(0) , next_index_(0) , next_element_(0) { } // ----------------------------------------------------------------- /*! Make use of copy constructor an error \param v vector that we are attempting to make a copy of. */ sparse_pack(const sparse_pack& v) { // Error: // Probably a sparse_pack argument has been passed by value CPPAD_ASSERT_UNKNOWN(0); } // ----------------------------------------------------------------- /*! Destructor */ ~sparse_pack(void) { } // ----------------------------------------------------------------- /*! Change number of sets, set end, and initialize all sets as empty If \c n_set_in is zero, any memory currently allocated for this object is freed. Otherwise, new memory may be allocated for the sets (if needed). \param n_set_in is the number of sets in this vector of sets. \param end_in is the maximum element plus one (the minimum element is 0). */ void resize(size_t n_set_in, size_t end_in) { n_set_ = n_set_in; end_ = end_in; if( n_set_ == 0 ) { data_.free(); return; } // now start a new vector with empty sets Pack zero(0); data_.erase(); n_pack_ = ( 1 + (end_ - 1) / n_bit_ ); size_t i = n_set_ * n_pack_; if( i > 0 ) { data_.extend(i); while(i--) data_[i] = zero; } // values that signify past end of list next_index_ = n_set_; next_element_ = end_; } // ----------------------------------------------------------------- /*! Add one element to a set. \param index is the index for this set in the vector of sets. \param element is the element we are adding to the set. \par Checked Assertions \li index < n_set_ \li element < end_ */ void add_element(size_t index, size_t element) { static Pack one(1); CPPAD_ASSERT_UNKNOWN( index < n_set_ ); CPPAD_ASSERT_UNKNOWN( element < end_ ); size_t j = element / n_bit_; size_t k = element - j * n_bit_; Pack mask = one << k; data_[ index * n_pack_ + j] |= mask; } // ----------------------------------------------------------------- /*! Is an element of a set. \param index is the index for this set in the vector of sets. \param element is the element we are checking to see if it is in the set. \par Checked Assertions \li index < n_set_ \li element < end_ */ bool is_element(size_t index, size_t element) { static Pack one(1); static Pack zero(0); CPPAD_ASSERT_UNKNOWN( index < n_set_ ); CPPAD_ASSERT_UNKNOWN( element < end_ ); size_t j = element / n_bit_; size_t k = element - j * n_bit_; Pack mask = one << k; return (data_[ index * n_pack_ + j] & mask) != zero; } // ----------------------------------------------------------------- /*! Begin retrieving elements from one of the sets. \param index is the index for the set that is going to be retrieved. The elements of the set are retrieved in increasing order. \par Checked Assertions \li index < n_set_ */ void begin(size_t index) { // initialize element to search for in this set CPPAD_ASSERT_UNKNOWN( index < n_set_ ); next_index_ = index; next_element_ = 0; } /*! Get the next element from the current retrieval set. \return is the next element in the set with index specified by the previous call to \c begin. If no such element exists, \c this->end() is returned. */ size_t next_element(void) { static Pack one(1); CPPAD_ASSERT_UNKNOWN( next_index_ < n_set_ ); CPPAD_ASSERT_UNKNOWN( next_element_ <= end_ ); if( next_element_ == end_ ) return end_; // initialize packed data index size_t j = next_element_ / n_bit_; // initialize bit index size_t k = next_element_ - j * n_bit_; // start search at this packed value Pack check = data_[ next_index_ * n_pack_ + j ]; while( true ) { // increment next element before checking this one next_element_++; // check if this element is in the set if( check & (one << k) ) return next_element_ - 1; // check if no more elements in the set if( next_element_ == end_ ) return end_; // increment bit index in Pack value so corresponds to // next element k++; CPPAD_ASSERT_UNKNOWN( k <= n_bit_ ); if( k == n_bit_ ) { // get next packed value k = 0; j++; CPPAD_ASSERT_UNKNOWN( j < n_pack_ ); check = data_[ next_index_ * n_pack_ + j ]; } } // should never get here CPPAD_ASSERT_UNKNOWN(false); return end_; } // ----------------------------------------------------------------- /*! Assign the empty set to one of the sets. \param target is the index of the set we are setting to the empty set. \par Checked Assertions \li target < n_set_ */ void clear(size_t target) { // value with all its bits set to false static Pack zero(0); CPPAD_ASSERT_UNKNOWN( target < n_set_ ); size_t t = target * n_pack_; size_t j = n_pack_; while(j--) data_[t++] = zero; } // ----------------------------------------------------------------- /*! Assign one set equal to another set. \param this_target is the index (in this \c sparse_pack object) of the set being assinged. \param other_value is the index (in the other \c sparse_pack object) of the that we are using as the value to assign to the target set. \param other is the other \c sparse_pack object (which may be the same as this \c sparse_pack object). \par Checked Assertions \li this_target < n_set_ \li other_value < other.n_set_ \li n_pack_ == other.n_pack_ */ void assignment( size_t this_target , size_t other_value , const sparse_pack& other ) { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ ); CPPAD_ASSERT_UNKNOWN( other_value < other.n_set_ ); CPPAD_ASSERT_UNKNOWN( n_pack_ == other.n_pack_ ); size_t t = this_target * n_pack_; size_t v = other_value * n_pack_; size_t j = n_pack_; while(j--) data_[t++] = other.data_[v++]; } // ----------------------------------------------------------------- /*! Assing a set equal to the union of two other sets. \param this_target is the index (in this \c sparse_pack object) of the set being assinged. \param this_left is the index (in this \c sparse_pack object) of the left operand for the union operation. It is OK for \a this_target and \a this_left to be the same value. \param other_right is the index (in the other \c sparse_pack object) of the right operand for the union operation. It is OK for \a this_target and \a other_right to be the same value. \param other is the other \c sparse_pack object (which may be the same as this \c sparse_pack object). \par Checked Assertions \li this_target < n_set_ \li this_left < n_set_ \li other_right < other.n_set_ \li n_pack_ == other.n_pack_ */ void binary_union( size_t this_target , size_t this_left , size_t other_right , const sparse_pack& other ) { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ ); CPPAD_ASSERT_UNKNOWN( this_left < n_set_ ); CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_ ); CPPAD_ASSERT_UNKNOWN( n_pack_ == other.n_pack_ ); size_t t = this_target * n_pack_; size_t l = this_left * n_pack_; size_t r = other_right * n_pack_; size_t j = n_pack_; while(j--) data_[t++] = ( data_[l++] | other.data_[r++] ); } // ----------------------------------------------------------------- /*! Amount of memory used by this vector of sets \return The amount of memory in units of type unsigned char memory. */ size_t memory(void) const { return n_set_ * n_pack_ * sizeof(Pack); } // ----------------------------------------------------------------- /*! Fetch n_set for vector of sets object. \return Number of from sets for this vector of sets object */ size_t n_set(void) const { return n_set_; } // ----------------------------------------------------------------- /*! Fetch end for this vector of sets object. \return is the maximum element value plus one (the minimum element value is 0). */ size_t end(void) const { return end_; } }; /*! Copy a user vector of bools sparsity pattern to an internal sparse_pack object. \tparam VectorBool is a simple vector with elements of type bool. \param internal The input value of sparisty does not matter. Upon return it contains the same sparsity pattern as \c user (or the transposed sparsity pattern). \param user sparsity pattern that we are placing \c internal. \param n_row number of rows in the sparsity pattern in \c user (rand dimension). \param n_col number of columns in the sparsity pattern in \c user (domain dimension). \param transpose if true, the sparsity pattern in \c internal is the transpose of the one in \c user. Otherwise it is the same sparsity pattern. */ template void sparsity_user2internal( sparse_pack& internal , const VectorBool& user , size_t n_row , size_t n_col , bool transpose ) { CPPAD_ASSERT_UNKNOWN( n_row * n_col == size_t(user.size()) ); size_t i, j; CPPAD_ASSERT_KNOWN( size_t( user.size() ) == n_row * n_col, "Size of this vector of bools sparsity pattern is not equal product " "of the domain and range dimensions for corresponding function." ); // transposed pattern case if( transpose ) { internal.resize(n_col, n_row); for(j = 0; j < n_col; j++) { for(i = 0; i < n_row; i++) { if( user[ i * n_col + j ] ) internal.add_element(j, i); } } return; } // same pattern case internal.resize(n_row, n_col); for(i = 0; i < n_row; i++) { for(j = 0; j < n_col; j++) { if( user[ i * n_col + j ] ) internal.add_element(i, j); } } return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/base_std_math.hpp0000644000176200001440000001326314536067013020775 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BASE_STD_MATH_INCLUDED # define CPPAD_BASE_STD_MATH_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin base_std_math$$ $spell inline fabs isnan alloc std acos asin atan cos exp sqrt const CppAD namespace erf $$ $section Base Type Requirements for Standard Math Functions$$ $index math, base require$$ $index base, math require$$ $index require, base math$$ $head Purpose$$ These definitions are required for the user's code to use the type $codei%AD<%Base%>%$$: $head Unary Standard Math$$ $index math, base unary$$ $index base, unary math$$ $index unary, base math$$ The type $icode Base$$ must support the following functions unary standard math functions (in the CppAD namespace): $table $bold Syntax$$ $cnext $bold Result$$ $rnext $icode%y% = abs(%x%)%$$ $cnext absolute value $rnext $icode%y% = acos(%x%)%$$ $cnext inverse cosine $rnext $icode%y% = asin(%x%)%$$ $cnext inverse sine $rnext $icode%y% = atan(%x%)%$$ $cnext inverse tangent $rnext $icode%y% = cos(%x%)%$$ $cnext cosine $rnext $icode%y% = cosh(%x%)%$$ $cnext hyperbolic cosine $rnext $icode%y% = exp(%x%)%$$ $cnext exponential $rnext $icode%y% = fabs(%x%)%$$ $cnext absolute value $rnext $icode%y% = log(%x%)%$$ $cnext natural logarithm $rnext $icode%y% = sin(%x%)%$$ $cnext sine $rnext $icode%y% = sinh(%x%)%$$ $cnext hyperbolic sine $rnext $icode%y% = sqrt(%x%)%$$ $cnext square root $rnext $icode%y% = tan(%x%)%$$ $cnext tangent $tend where the arguments and return value have the prototypes $codei% const %Base%& %x% %Base% %y% %$$ For example, $cref/base_alloc/base_alloc.hpp/Unary Standard Math/$$, $head CPPAD_STANDARD_MATH_UNARY$$ $index CPPAD_STANDARD_MATH_UNARY$$ The macro invocation, within the CppAD namespace, $codei% CPPAD_STANDARD_MATH_UNARY(%Base%, %Fun%) %$$ defines the syntax $codei% %y% = CppAD::%Fun%(%x%) %$$ This macro uses the functions $codei%std::%Fun%$$ which must be defined and have the same prototype as $codei%CppAD::%Fun%$$. For example, $cref/float/base_float.hpp/Unary Standard Math/$$. $head erf$$ $index erf, base require$$ $index base, erf require$$ $index require, base erf$$ If the error function is supported by the compiler, $cref/CPPAD_COMPILER_HAS_ERF/erf/Method/CPPAD_COMPILER_HAS_ERF/$$ is one, the type $icode Base$$ must support the syntax $codei% %y% = CppAD::erf(%x%) %$$ where $icode x$$ and $icode y$$ have the same prototype as above. For example, see $cref/base_alloc/base_alloc.hpp/erf/$$. $head sign$$ $index sign, base require$$ $index base, sign require$$ $index require, base sign$$ The type $icode Base$$ must support the syntax $codei% %y% = CppAD::sign(%x%) %$$ which computes $latex \[ y = \left\{ \begin{array}{ll} +1 & {\rm if} \; x > 0 \\ 0 & {\rm if} \; x = 0 \\ -1 & {\rm if} \; x < 0 \end{array} \right. \] $$ where $icode x$$ and $icode y$$ have the same prototype as above. For example, see $cref/base_alloc/base_alloc.hpp/sign/$$. Note that, if ordered comparisons are not defined for the type $icode Base$$, the $code code sign$$ function should generate an assert if it is used; see $cref/complex invalid unary math/base_complex.hpp/Invalid Unary Math/$$. $head pow$$ $index pow, base require$$ $index base, pow require$$ $index require, base pow$$ The type $icode Base$$ must support the syntax $codei% %z% = CppAD::pow(%x%, %y%) %$$ which computes $latex z = x^y$$. The arguments $icode x$$ and $icode y$$ have prototypes $codei% const %Base%& %x% const %Base%& %y% %$$ and the return value $icode z$$ has prototype $codei% %Base% %z% %$$ For example, see $cref/base_alloc/base_alloc.hpp/pow/$$. $head isnan$$ $index isnan, base type$$ $index base, isnan$$ If $icode Base$$ defines the $code isnan$$ function, you may also have to provide a definition in the CppAD namespace (to avoid a function ambiguity). For example, see $cref/base_complex/base_complex.hpp/isnan/$$. $head limits$$ $index numeric, limits Base$$ $index limits, numeric Base$$ $index Base, numeric_limits$$ The $cref/numeric_limits/limits/$$ functions $codei% %Base% CppAD::numeric_limits<%Base%>::epsilon() %Base% CppAD::numeric_limits<%Base%>::min() %Base% CppAD::numeric_limits<%Base%>::max() %$$ must return machine epsilon, minimum positive normalize value, and maximum finite value for the type $icode Base$$. $subhead epsilon$$ The deprecated function $cref epsilon$$ function must also be included. It can be implemented using $codei% namespace CppAD { template <> inline %Base% epsilon<%Base%>(void) { return numeric_limits<%Base%>::epsilon(); } } %$$ $end ------------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file base_std_math.hpp Defintions that aid meeting Base type requirements for standard math functions. */ /*! \def CPPAD_STANDARD_MATH_UNARY(Type, Fun) This macro defines the function \verbatim y = CppAD:Fun(x) \endverbatim where the argument \c x and return value \c y have type \c Type using the corresponding function std::Fun. */ # define CPPAD_STANDARD_MATH_UNARY(Type, Fun) \ inline Type Fun(const Type& x) \ { return std::Fun(x); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sign.hpp0000644000176200001440000000615214536067013017137 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SIGN_INCLUDED # define CPPAD_SIGN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin sign$$ $spell Dirac Vec std faq Taylor Cpp namespace const $$ $index sign, AD$$ $section Sign Function$$ $head Syntax$$ $icode%y% = sign(%x%)%$$ $head Purpose$$ Evaluates the $code sign$$ function which is defined by $latex \[ {\rm sign} (x ) = \left\{ \begin{array}{rl} +1 & {\rm if} \; x > 0 \\ 0 & {\rm if} \; x = 0 \\ -1 & {\rm if} \; x < 0 \end{array} \right. \] $$ $head x$$ The argument $icode x$$ has one of the following prototypes $codei% const AD<%Base%> &%x% const VecAD<%Base%>::reference &%x% %$$ $head y$$ The result $icode y$$ has prototype $codei% AD<%Base%> %y% %$$ $head Operation Sequence$$ This is an AD of $icode Base$$ $cref/atomic operation/glossary/Operation/Atomic/$$ and hence is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Complex Types$$ The $code sign$$ function is not defined for the AD type sequences above $code std::complex$$ or $code std::complex$$ because these are not $cref/ordered types/base_ordered/Ordered Type/$$. $head Derivative$$ CppAD computes the derivative of the $code sign$$ function as zero for all argument values $icode x$$. The correct mathematical derivative is different and is given by $latex \[ {\rm sign}{(1)} (x) = 2 \delta (x) \] $$ where $latex \delta (x)$$ is the Dirac Delta function. $head Example$$ $children% example/sign.cpp %$$ The file $cref sign.cpp$$ contains an example and test of this function. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD AD::Sign (void) const { AD result; result.value_ = sign(value_); CPPAD_ASSERT_UNKNOWN( Parameter(result) ); if( Variable(*this) ) { // add this operation to the tape CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 ); ADTape *tape = tape_this(); // corresponding operand address tape->Rec_.PutArg(taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(SignOp); // make result a variable result.tape_id_ = tape->id_; } return result; } template inline AD sign(const AD &x) { return x.Sign(); } template inline AD sign(const VecAD_reference &x) { return sign( x.ADBase() ); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/rev_sparse_hes.hpp0000644000176200001440000004505514536067013021214 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_REV_SPARSE_HES_INCLUDED # define CPPAD_REV_SPARSE_HES_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin RevSparseHes$$ $spell std VecAD Jacobian Jac Hessian Hes const Bool Dep proportional var $$ $section Hessian Sparsity Pattern: Reverse Mode$$ $index RevSparseHes$$ $index reverse, sparse Hessian$$ $index sparse, reverse Hessian$$ $index pattern, reverse Hessian$$ $head Syntax$$ $icode%h% = %f%.RevSparseHes(%q%, %s%) %$$ $icode%h% = %f%.RevSparseHes(%q%, %s%, %transpose%)%$$ $head Purpose$$ We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. For a fixed matrix $latex R \in \B{R}^{n \times q}$$ and a fixed vector $latex S \in \B{R}^{1 \times m}$$, we define $latex \[ \begin{array}{rcl} H(x) & = & \partial_x \left[ \partial_u S * F[ x + R * u ] \right]_{u=0} \\ & = & R^\R{T} * (S * F)^{(2)} ( x ) \\ H(x)^\R{T} & = & (S * F)^{(2)} ( x ) * R \end{array} \] $$ Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex R$$ and the vector $latex S$$, $code RevSparseHes$$ returns a sparsity pattern for the $latex H(x)$$. $head f$$ The object $icode f$$ has prototype $codei% const ADFun<%Base%> %f% %$$ $head x$$ the sparsity pattern is valid for all values of the independent variables in $latex x \in \B{R}^n$$ (even if it has $cref CondExp$$ or $cref VecAD$$ operations). $head q$$ The argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of columns in $latex R \in \B{R}^{n \times q}$$ and the number of rows in $latex H(x) \in \B{R}^{q \times n}$$. It must be the same value as in the previous $cref ForSparseJac$$ call $codei% %f%.ForSparseJac(%q%, %r%, %r_transpose%) %$$ Note that if $icode r_transpose$$ is true, $icode r$$ in the call above corresponding to $latex R^\R{T} \in \B{R}^{q \times n}$$ $head transpose$$ The argument $icode transpose$$ has prototype $codei% bool %transpose% %$$ The default value $code false$$ is used when $icode transpose$$ is not present. $head r$$ The matrix $latex R$$ is specified by the previous call $codei% %f%.ForSparseJac(%q%, %r%, %transpose%) %$$ see $cref/r/ForSparseJac/r/$$. The type of the elements of $cref/VectorSet/RevSparseHes/VectorSet/$$ must be the same as the type of the elements of $icode r$$. $head s$$ The argument $icode s$$ has prototype $codei% const %VectorSet%& %s% %$$ (see $cref/VectorSet/RevSparseHes/VectorSet/$$ below) If it has elements of type $code bool$$, its size is $latex m$$. If it has elements of type $code std::set$$, its size is one and all the elements of $icode%s%[0]%$$ are between zero and $latex m - 1$$. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the vector $icode S$$. $head h$$ The result $icode h$$ has prototype $codei% %VectorSet%& %h% %$$ (see $cref/VectorSet/RevSparseHes/VectorSet/$$ below). $subhead transpose false$$ If $icode h$$ has elements of type $code bool$$, its size is $latex q * n$$. If it has elements of type $code std::set$$, its size is $latex q$$ and all the set elements are between zero and $icode%n%-1%$$ inclusive. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex H(x)$$. $subhead transpose true$$ If $icode h$$ has elements of type $code bool$$, its size is $latex n * q$$. If it has elements of type $code std::set$$, its size is $latex n$$ and all the set elements are between zero and $icode%q%-1%$$ inclusive. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex H(x)^\R{T}$$. $head VectorSet$$ The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code bool$$ or $code std::set$$; see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion of the difference. The type of the elements of $cref/VectorSet/RevSparseHes/VectorSet/$$ must be the same as the type of the elements of $icode r$$. $head Entire Sparsity Pattern$$ Suppose that $latex q = n$$ and $latex R \in \B{R}^{n \times n}$$ is the $latex n \times n$$ identity matrix. Further suppose that the $latex S$$ is the $th k$$ $cref/elementary vector/glossary/Elementary Vector/$$; i.e. $latex \[ S_j = \left\{ \begin{array}{ll} 1 & {\rm if} \; j = k \\ 0 & {\rm otherwise} \end{array} \right. \] $$ In this case, the corresponding value $icode h$$ is a sparsity pattern for the Hessian matrix $latex F_k^{(2)} (x) \in \B{R}^{n \times n}$$. $head Example$$ $children% example/rev_sparse_hes.cpp %$$ The file $cref rev_sparse_hes.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file rev_sparse_hes.hpp Reverse mode Hessian sparsity patterns. */ /*! Calculate Hessian sparsity patterns using reverse mode. The C++ source code corresponding to this operation is \verbatim h = f.RevSparseHes(q, s) \endverbatim \tparam Base is the base type for this recording. \tparam VectorSet is a simple vector with elements of type \c bool. \param transpose is true (false) if \c is is equal to \f$ H(x) \f$ (\f$ H(x)^T \f$) where \f[ H(x) = R^T (S * F)^{(2)} (x) \f] where \f$ F \f$ is the function corresponding to the operation sequence and \a x is any argument value. \param q is the value of \a q in the by the previous call of the form \verbatim f.ForSparseJac(q, r) \endverbatim The value \c r in this call is a sparsity pattern for the matrix \f$ R \f$. \param s is a vector with size \c m that specifies the sparsity pattern for the vector \f$ S \f$, where \c m is the number of dependent variables corresponding to the operation sequence stored in \a play. \param h the input value of \a h must be a vector with size \c q*n. The input value of its elements does not matter. On output, \a h is the sparsity pattern for the matrix \f$ H(x) \f$ or \f$ H(x)^T \f$ depending on \c transpose. \param num_var is the total number of variables in this recording. \param dep_taddr maps dependendent variable index to the corresponding variable in the tape. \param ind_taddr maps independent variable index to the corresponding variable in the tape. \param play is the recording that defines the function we are computing the sparsity pattern for. \param for_jac_sparsity is a vector of sets containing the the forward Jacobian sparsity pattern corresponding to $latex R$$ for all of the variables on the tape. */ template void RevSparseHesBool( bool transpose , size_t q , const VectorSet& s , VectorSet& h , size_t num_var , CppAD::vector& dep_taddr , CppAD::vector& ind_taddr , CppAD::player& play , sparse_pack& for_jac_sparsity ) { // temporary indices size_t i, j; // check Vector is Simple VectorSet class with bool elements CheckSimpleVector(); // range and domain dimensions for F size_t m = dep_taddr.size(); size_t n = ind_taddr.size(); CPPAD_ASSERT_KNOWN( q == for_jac_sparsity.end(), "RevSparseHes: q is not equal to its value\n" "in the previous call to ForSparseJac with this ADFun object." ); CPPAD_ASSERT_KNOWN( size_t(s.size()) == m, "RevSparseHes: size of s is not equal to\n" "range dimension for ADFun object." ); // Array that will hold reverse Jacobian dependency flag. // Initialize as true for the dependent variables. pod_vector RevJac; RevJac.extend(num_var); for(i = 0; i < num_var; i++) RevJac[i] = false; for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr[i] < num_var ); RevJac[ dep_taddr[i] ] = s[i]; } // vector of sets that will hold reverse Hessain values sparse_pack rev_hes_sparsity; rev_hes_sparsity.resize(num_var, q); // compute the Hessian sparsity patterns RevHesSweep( n, num_var, &play, for_jac_sparsity, RevJac.data(), rev_hes_sparsity ); // return values corresponding to independent variables CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == n * q ); for(j = 0; j < n; j++) { for(i = 0; i < q; i++) { if( transpose ) h[ j * q + i ] = false; else h[ i * n + j ] = false; } } // j is index corresponding to reverse mode partial for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr[j] < num_var ); // ind_taddr[j] is operator taddr for j-th independent variable CPPAD_ASSERT_UNKNOWN( ind_taddr[j] == j + 1 ); CPPAD_ASSERT_UNKNOWN( play.GetOp( ind_taddr[j] ) == InvOp ); // extract the result from rev_hes_sparsity CPPAD_ASSERT_UNKNOWN( rev_hes_sparsity.end() == q ); rev_hes_sparsity.begin(j + 1); i = rev_hes_sparsity.next_element(); while( i < q ) { if( transpose ) h[ j * q + i ] = true; else h[ i * n + j ] = true; i = rev_hes_sparsity.next_element(); } } return; } /*! Calculate Hessian sparsity patterns using reverse mode. The C++ source code corresponding to this operation is \verbatim h = f.RevSparseHes(q, s) \endverbatim \tparam Base is the base type for this recording. \tparam VectorSet is a simple vector with elements of type \c std::set. \param transpose is true (false) if \c is is equal to \f$ H(x) \f$ (\f$ H(x)^T \f$) where \f[ H(x) = R^T (S * F)^{(2)} (x) \f] where \f$ F \f$ is the function corresponding to the operation sequence and \a x is any argument value. \param q is the value of \a q in the by the previous call of the form \verbatim f.ForSparseJac(q, r) \endverbatim The value \c r in this call is a sparsity pattern for the matrix \f$ R \f$. \param s is a vector with size \c m that specifies the sparsity pattern for the vector \f$ S \f$, where \c m is the number of dependent variables corresponding to the operation sequence stored in \a play. \param h If \c transpose, the input value of \a h must be a vector with size \a q. Otherwise, its input value must have size \c n; On input, each element of \a h must be an empty set. On output, \a h is the sparsity pattern for the matrix \f$ H(x) \f$ or \f$ H(x)^T \f$ depending on \c transpose. \param num_var is the total number of variables in this recording. \param dep_taddr maps dependendent variable index to the corresponding variable in the tape. \param ind_taddr maps independent variable index to the corresponding variable in the tape. \param play is the recording that defines the function we are computing the sparsity pattern for. \param for_jac_sparsity is a vector of sets containing the the forward Jacobian sparsity pattern corresponding to $latex R$$ for all of the variables on the tape. */ template void RevSparseHesSet( bool transpose , size_t q , const VectorSet& s , VectorSet& h , size_t num_var , CppAD::vector& dep_taddr , CppAD::vector& ind_taddr , CppAD::player& play , CPPAD_INTERNAL_SPARSE_SET& for_jac_sparsity ) { // temporary indices size_t i, j; std::set::const_iterator itr; // check VectorSet is Simple Vector class with sets for elements CheckSimpleVector, VectorSet>( one_element_std_set(), two_element_std_set() ); // range and domain dimensions for F # ifndef NDEBUG size_t m = dep_taddr.size(); # endif size_t n = ind_taddr.size(); CPPAD_ASSERT_KNOWN( q == for_jac_sparsity.end(), "RevSparseHes: q is not equal to its value\n" "in the previous call to ForSparseJac with this ADFun object." ); CPPAD_ASSERT_KNOWN( s.size() == 1, "RevSparseHes: size of s is not equal to one." ); // Array that will hold reverse Jacobian dependency flag. // Initialize as true for the dependent variables. pod_vector RevJac; RevJac.extend(num_var); for(i = 0; i < num_var; i++) RevJac[i] = false; itr = s[0].begin(); while( itr != s[0].end() ) { i = *itr++; CPPAD_ASSERT_KNOWN( i < m, "RevSparseHes: an element of the set s[0] has value " "greater than or equal m" ); CPPAD_ASSERT_UNKNOWN( dep_taddr[i] < num_var ); RevJac[ dep_taddr[i] ] = true; } // vector of sets that will hold reverse Hessain values CPPAD_INTERNAL_SPARSE_SET rev_hes_sparsity; rev_hes_sparsity.resize(num_var, q); // compute the Hessian sparsity patterns RevHesSweep( n, num_var, &play, for_jac_sparsity, RevJac.data(), rev_hes_sparsity ); // return values corresponding to independent variables // j is index corresponding to reverse mode partial CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == q || transpose ); CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == n || ! transpose ); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr[j] < num_var ); CPPAD_ASSERT_UNKNOWN( ind_taddr[j] == j + 1 ); CPPAD_ASSERT_UNKNOWN( play.GetOp( ind_taddr[j] ) == InvOp ); // extract the result from rev_hes_sparsity // and add corresponding elements to result sets in h CPPAD_ASSERT_UNKNOWN( rev_hes_sparsity.end() == q ); rev_hes_sparsity.begin(j+1); i = rev_hes_sparsity.next_element(); while( i < q ) { if( transpose ) h[j].insert(i); else h[i].insert(j); i = rev_hes_sparsity.next_element(); } } return; } /*! User API for Hessian sparsity patterns using reverse mode. The C++ source code corresponding to this operation is \verbatim h = f.RevSparseHes(q, r) \endverbatim \tparam Base is the base type for this recording. \tparam VectorSet is a simple vector with elements of type \c bool or \c std::set. \param transpose is true (false) if \c is is equal to \f$ H(x) \f$ (\f$ H(x)^T \f$) where \f[ H(x) = R^T (S * F)^{(2)} (x) \f] where \f$ F \f$ is the function corresponding to the operation sequence and \a x is any argument value. \param q is the value of \a q in the by the previous call of the form \verbatim f.ForSparseJac(q, r, packed) \endverbatim The value \c r in this call is a sparsity pattern for the matrix \f$ R \f$. The type of the element of \c r for the previous call to \c ForSparseJac must be the same as the type of the elements of \c s. \param s is a vector with size \c m that specifies the sparsity pattern for the vector \f$ S \f$, where \c m is the number of dependent variables corresponding to the operation sequence stored in \a play. \return If \c transpose is false (true), the return vector is a sparsity pattern for \f$ H(x) \f$ (\f$ H(x)^T \f$). \f[ H(x) = R^T ( S * F)^{(2)} (x) \f] where \f$ F \f$ is the function corresponding to the operation sequence and \a x is any argument value. */ template template VectorSet ADFun::RevSparseHes( size_t q, const VectorSet& s, bool transpose ) { VectorSet h; typedef typename VectorSet::value_type Set_type; // Should check to make sure q is same as in previous call to // forward sparse Jacobian. RevSparseHesCase( Set_type() , transpose , q , s , h ); return h; } /*! Private helper function for RevSparseHes(q, s). All of the description in the public member function RevSparseHes(q, s) applies. \param set_type is a \c bool value. This argument is used to dispatch to the proper source code depending on the vlaue of \c VectorSet::value_type. \param transpose See \c RevSparseHes(q, s). \param q See \c RevSparseHes(q, s). \param s See \c RevSparseHes(q, s). \param h is the return value for the corresponging call to \c RevSparseJac(q, s). */ template template void ADFun::RevSparseHesCase( bool set_type , bool transpose , size_t q , const VectorSet& s , VectorSet& h ) { size_t n = Domain(); h.resize(q * n ); CPPAD_ASSERT_KNOWN( for_jac_sparse_pack_.n_set() > 0, "RevSparseHes: previous stored call to ForSparseJac did not " "use bool for the elements of r." ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == 0 ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == num_var_tape_ ); // use sparse_pack for the calculation CppAD::RevSparseHesBool( transpose , q , s , h , num_var_tape_ , dep_taddr_ , ind_taddr_ , play_ , for_jac_sparse_pack_ ); } /*! Private helper function for RevSparseHes(q, s). All of the description in the public member function RevSparseHes(q, s) applies. \param set_type is a \c std::set value. This argument is used to dispatch to the proper source code depending on the vlaue of \c VectorSet::value_type. \param transpose See \c RevSparseHes(q, s). \param q See \c RevSparseHes(q, s). \param s See \c RevSparseHes(q, s). \param h is the return value for the corresponging call to \c RevSparseJac(q, s). */ template template void ADFun::RevSparseHesCase( const std::set& set_type , bool transpose , size_t q , const VectorSet& s , VectorSet& h ) { size_t n = Domain(); if( transpose ) h.resize(n); else h.resize(q); CPPAD_ASSERT_KNOWN( for_jac_sparse_set_.n_set() > 0, "RevSparseHes: previous stored call to ForSparseJac did not " "use std::set for the elements of r." ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == 0 ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == num_var_tape_ ); // use sparse_pack for the calculation CppAD::RevSparseHesSet( transpose , q , s , h , num_var_tape_ , dep_taddr_ , ind_taddr_ , play_ , for_jac_sparse_set_ ); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/erf.hpp0000644000176200001440000000671314536067013016756 0ustar liggesusers// $Id:$ # ifndef CPPAD_ERF_INCLUDED # define CPPAD_ERF_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin erf$$ $section The AD Error Function$$ $spell std cmath Vedder Cpp namespace Vec erf const $$ $index erf, AD function$$ $index error, AD function$$ $index function, error AD$$ $head Syntax$$ $icode%y% = erf(%x%)%$$ $head Description$$ Returns the value of the error function which is defined by $latex \[ {\rm erf} (x) = \frac{2}{ \sqrt{\pi} } \int_0^x \exp( - t * t ) \; {\bf d} t \] $$ $head x$$ The argument $icode x$$, and the result $icode y$$ have one of the following paris of prototypes: $codei% const float%% &%x%, float%% %y% const double%% &%x%, double%% %y% const AD<%Base%> &%x%, AD<%Base%> %y% const VecAD<%Base%>::reference &%x%, AD<%Base%> %y% %$$ $head Operation Sequence$$ The AD of $icode Base$$ operation sequence used to calculate $icode y$$ is $cref/independent/glossary/Operation/Independent/$$ of $icode x$$. $head Method$$ $subhead CPPAD_COMPILER_HAS_ERF$$ $index CPPAD_COMPILER_HAS_ERF$$ This preprocessor symbol is one if the function $codei%std::erf(double %x%)%$$ is defined the in the include file $code $$. Otherwise this preprocessor symbol is zero. If this preprocessor symbols is one, CppAD uses the compiler's version of $code erf$$ and it corresponds to an $cref/atomic/glossary/Operation/Atomic/$$ operation. $subhead Other$$ If the function $codei%std::erf(double %x%)%$$ is not defined, CppAD uses a fast approximation (few numerical operations) with relative error bound $latex 4 \times 10^{-4}$$; see Vedder, J.D., $icode Simple approximations for the error function and its inverse$$, American Journal of Physics, v 55, n 8, 1987, p 762-3. $head Example$$ $children% example/erf.cpp %$$ The file $cref erf.cpp$$ contains an example and test of this function. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------- */ # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include # if ! CPPAD_COMPILER_HAS_ERF // BEGIN CppAD namespace namespace CppAD { template Type erf_template(const Type &x) { using CppAD::exp; const Type a = static_cast(993./880.); const Type b = static_cast(89./880.); return tanh( (a + b * x * x) * x ); } inline float erf(const float &x) { return erf_template(x); } inline double erf(const double &x) { return erf_template(x); } template inline AD erf(const AD &x) { return erf_template(x); } template inline AD erf(const VecAD_reference &x) { return erf_template( x.ADBase() ); } } // END CppAD namespace # endif // CPPAD_COMPILER_HAS_ERF # endif // CPPAD_ERF_INCLUDED TMB/inst/include/cppad/local/par_var.hpp0000644000176200001440000000604414536067013017631 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_PAR_VAR_INCLUDED # define CPPAD_PAR_VAR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- $begin ParVar$$ $spell VecAD const bool $$ $index Parameter$$ $index Variable$$ $section Is an AD Object a Parameter or Variable$$ $head Syntax$$ $icode%b% = Parameter(%x%)%$$ $pre $$ $icode%b% = Variable(%x%)%$$ $head Purpose$$ Determine if $icode x$$ is a $cref/parameter/glossary/Parameter/$$ or $cref/variable/glossary/Variable/$$. $head x$$ The argument $icode x$$ has prototype $codei% const AD<%Base%> &%x% const VecAD<%Base%> &%x% %$$ $head b$$ The return value $icode b$$ has prototype $codei% bool %b% %$$ The return value for $code Parameter$$ ($code Variable$$) is true if and only if $icode x$$ is a parameter (variable). Note that a $cref/VecAD/VecAD/$$ object is a variable if any element of the vector depends on the independent variables. $head Operation Sequence$$ The result of this operation is not an $cref/AD of Base/glossary/AD of Base/$$ object. Thus it will not be recorded as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Example$$ $children% example/par_var.cpp %$$ The file $cref par_var.cpp$$ contains an example and test of these functions. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ namespace CppAD { // Parameter template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool Parameter(const AD &x) { if( x.tape_id_ == 0 ) return true; size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS); return x.tape_id_ != *AD::tape_id_ptr(thread); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool Parameter(const VecAD &x) { if( x.tape_id_ == 0 ) return true; size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS); return x.tape_id_ != *AD::tape_id_ptr(thread); } // Variable template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool Variable(const AD &x) { if( x.tape_id_ == 0 ) return false; size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS); return x.tape_id_ == *AD::tape_id_ptr(thread); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool Variable(const VecAD &x) { if( x.tape_id_ == 0 ) return false; size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS); return x.tape_id_ == *AD::tape_id_ptr(thread); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/ad_binary.hpp0000644000176200001440000000730214536067013020125 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_AD_BINARY_INCLUDED # define CPPAD_AD_BINARY_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin ad_binary$$ $spell Op VecAD const $$ $section AD Binary Arithmetic Operators$$ $index binary, operator$$ $index operator, binary$$ $index +, binary operator$$ $index add, binary operator$$ $index plus, binary operator$$ $index -, binary operator$$ $index subtract, binary operator$$ $index minus, binary operator$$ $index *, binary operator$$ $index multiply, binary operator$$ $index times, binary operator$$ $index /, binary operator$$ $index divide, binary operator$$ $head Syntax$$ $icode%z% = %x% %Op% %y%$$ $head Purpose$$ Performs arithmetic operations where either $icode x$$ or $icode y$$ has type $codei%AD<%Base%>%$$ or $cref%VecAD::reference%VecAD%VecAD::reference%$$. $head Op$$ The operator $icode Op$$ is one of the following $table $bold Op$$ $cnext $bold Meaning$$ $rnext $code +$$ $cnext $icode z$$ is $icode x$$ plus $icode y$$ $rnext $code -$$ $cnext $icode z$$ is $icode x$$ minus $icode y$$ $rnext $code *$$ $cnext $icode z$$ is $icode x$$ times $icode y$$ $rnext $code /$$ $cnext $icode z$$ is $icode x$$ divided by $icode y$$ $tend $head Base$$ The type $icode Base$$ is determined by the operand that has type $codei%AD<%Base%>%$$ or $codei%VecAD<%Base%>::reference%$$. $head x$$ The operand $icode x$$ has the following prototype $codei% const %Type% &%x% %$$ where $icode Type$$ is $codei%VecAD<%Base%>::reference%$$, $codei%AD<%Base%>%$$, $icode Base$$, or $code double$$. $head y$$ The operand $icode y$$ has the following prototype $codei% const %Type% &%y% %$$ where $icode Type$$ is $codei%VecAD<%Base%>::reference%$$, $codei%AD<%Base%>%$$, $icode Base$$, or $code double$$. $head z$$ The result $icode z$$ has the following prototype $codei% %Type% %z% %$$ where $icode Type$$ is $codei%AD<%Base%>%$$. $head Operation Sequence$$ This is an $cref/atomic/glossary/Operation/Atomic/$$ $cref/AD of Base/glossary/AD of Base/$$ operation and hence it is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $children% example/add.cpp% example/sub.cpp% example/mul.cpp% example/div.cpp %$$ $head Example$$ The following files contain examples and tests of these functions. Each test returns true if it succeeds and false otherwise. $table $rref add.cpp$$ $rref sub.cpp$$ $rref mul.cpp$$ $rref div.cpp$$ $tend $head Derivative$$ If $latex f$$ and $latex g$$ are $cref/Base functions/glossary/Base Function/$$ $subhead Addition$$ $latex \[ \D{[ f(x) + g(x) ]}{x} = \D{f(x)}{x} + \D{g(x)}{x} \] $$ $subhead Subtraction$$ $latex \[ \D{[ f(x) - g(x) ]}{x} = \D{f(x)}{x} - \D{g(x)}{x} \] $$ $subhead Multiplication$$ $latex \[ \D{[ f(x) * g(x) ]}{x} = g(x) * \D{f(x)}{x} + f(x) * \D{g(x)}{x} \] $$ $subhead Division$$ $latex \[ \D{[ f(x) / g(x) ]}{x} = [1/g(x)] * \D{f(x)}{x} - [f(x)/g(x)^2] * \D{g(x)}{x} \] $$ $end ----------------------------------------------------------------------------- */ # include # include # include # include # endif TMB/inst/include/cppad/local/parallel_ad.hpp0000644000176200001440000000705414536067013020441 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_PARALLEL_AD_INCLUDED # define CPPAD_PARALLEL_AD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin parallel_ad$$ $spell CppAD num std $$ $section Enable AD Calculations During Parallel Mode$$ $head Syntax$$ $codei%parallel_ad<%Base%>()%$$ $head Purpose$$ The function $codei%parallel_ad<%Base%>()%$$ must be called before any $codei%AD<%Base>%$$ objects are used in $cref/parallel/ta_in_parallel/$$ mode. In addition, if this routine is called after one is done using parallel mode, it will free extra memory used to keep track of the multiple $codei%AD<%Base%>%$$ tapes required for parallel execution. $head Discussion$$ By default, for each $codei%AD<%Base%>%$$ class there is only one tape that records $cref/AD of Base/glossary/AD of Base/$$ operations. This tape is a global variable and hence it cannot be used by multiple threads at the same time. The $cref/parallel_setup/ta_parallel_setup/$$ function informs CppAD of the maximum number of threads that can be active in parallel mode. This routine does extra setup (and teardown) for the particular $icode Base$$ type. $head CheckSimpleVector$$ This routine has the side effect of calling the routines $codei% CheckSimpleVector< %Type%, CppAD::vector<%Type%> >() %$$ where $icode Type$$ is $icode Base$$ and $codei%AD<%Base%>%$$. $head Example$$ The files $cref team_openmp.cpp$$, $cref team_bthread.cpp$$, and $cref team_pthread.cpp$$, contain examples and tests that implement this function. $head Restriction$$ This routine cannot be called in parallel mode or while there is a tape recording $codei%AD<%Base%>%$$ operations. $end ----------------------------------------------------------------------------- */ # include // BEGIN CppAD namespace namespace CppAD { /*! Enable parallel execution mode with AD by initializing static variables that my be used. */ template void parallel_ad(void) { CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "parallel_ad must be called before entering parallel execution mode." ); CPPAD_ASSERT_KNOWN( AD::tape_ptr() == CPPAD_NULL , "parallel_ad cannot be called while a tape recording is in progress" ); // ensure statics in following functions are initialized elapsed_seconds(); ErrorHandler::Current(); NumArg(BeginOp); NumRes(BeginOp); one_element_std_set(); two_element_std_set(); // the sparse_pack class has member functions with static data sparse_pack sp; sp.resize(1, 1); // so can call add_element sp.add_element(0, 0); // has static data sp.begin(0); // so can call next_element sp.next_element(); // has static data sp.clear(0); // has static data sp.is_element(0, 0); // has static data // statics that depend on the value of Base AD::tape_id_handle(0); AD::tape_handle(0); AD::tape_manage(tape_manage_clear); discrete::List(); CheckSimpleVector< Base, CppAD::vector >(); CheckSimpleVector< AD, CppAD::vector< AD > >(); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/value.hpp0000644000176200001440000000432414536067013017312 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_VALUE_INCLUDED # define CPPAD_VALUE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Value$$ $spell const $$ $index Value$$ $index Base, from AD$$ $index AD, convert to Base$$ $index convert, AD to Base$$ $section Convert From an AD Type to its Base Type$$ $head Syntax$$ $icode%b% = Value(%x%)%$$ $head Purpose$$ Converts from an AD type to the corresponding $cref/base type/glossary/Base Type/$$. $head x$$ The argument $icode x$$ has prototype $codei% const AD<%Base%> &%x% %$$ $head b$$ The return value $icode b$$ has prototype $codei% %Base% %b% %$$ $head Operation Sequence$$ The result of this operation is not an $cref/AD of Base/glossary/AD of Base/$$ object. Thus it will not be recorded as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Restriction$$ If the argument $icode x$$ is a $cref/variable/glossary/Variable/$$ its dependency information would not be included in the $code Value$$ result (see above). For this reason, the argument $icode x$$ must be a $cref/parameter/glossary/Parameter/$$; i.e., it cannot depend on the current $cref/independent variables/glossary/Tape/Independent Variable/$$. $head Example$$ $children% example/value.cpp %$$ The file $cref value.cpp$$ contains an example and test of this operation. $end ------------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION Base Value(const AD &x) { Base result; CPPAD_ASSERT_KNOWN( Parameter(x) , "Value: argument is a variable (not a parameter)" ); result = x.value_; return result; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/std_math_ad.hpp0000644000176200001440000002260014536067013020442 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_STD_MATH_AD_INCLUDED # define CPPAD_STD_MATH_AD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin std_math_ad$$ $spell Vec std atan const acos asin atan cos exp fabs sqrt CppAD namespace tanh $$ $index standard, AD math unary$$ $index math, AD unary$$ $index unary, AD math$$ $index acos, AD$$ $index asin, AD$$ $index atan, AD$$ $index cos, AD$$ $index cosh, AD$$ $index exp, AD$$ $index fabs, AD$$ $index log, AD$$ $index log10, AD$$ $index sin, AD$$ $index sinh, AD$$ $index sqrt, AD$$ $index tan, AD$$ $index tanh, AD$$ $section AD Standard Math Unary Functions$$ $head Syntax$$ $icode%y% = %fun%(%x%)%$$ $head Purpose$$ Evaluates the one argument standard math function $icode fun$$ where its argument is an $cref/AD of/glossary/AD of Base/$$ $icode Base$$ object. $head x$$ The argument $icode x$$ has one of the following prototypes $codei% const AD<%Base%> &%x% const VecAD<%Base%>::reference &%x% %$$ $head y$$ The result $icode y$$ has prototype $codei% AD<%Base%> %y% %$$ $head Operation Sequence$$ Most of these functions are AD of $icode Base$$ $cref/atomic operations/glossary/Operation/Atomic/$$. In all cases, The AD of $icode Base$$ operation sequence used to calculate $icode y$$ is $cref/independent/glossary/Operation/Independent/$$ of $icode x$$. $head fun$$ A definition of $icode fun$$ is included for each of the following functions: $code acos$$, $code asin$$, $code atan$$, $code cos$$, $code cosh$$, $code exp$$, $code fabs$$, $code log$$, $code log10$$, $code sin$$, $code sinh$$, $code sqrt$$, $code tan$$, $code tanh$$. $head Examples$$ The following files contain examples and tests of these functions. Each test returns true if it succeeds and false otherwise. $children% example/acos.cpp% example/asin.cpp% example/atan.cpp% example/cos.cpp% example/cosh.cpp% example/exp.cpp% example/log.cpp% example/log10.cpp% example/sin.cpp% example/sinh.cpp% example/sqrt.cpp% example/tan.cpp% example/tanh.cpp %$$ $table $rref abs.cpp$$ $rref Acos.cpp$$ $rref Asin.cpp$$ $rref atan.cpp$$ $rref cos.cpp$$ $rref cosh.cpp$$ $rref exp.cpp$$ $rref log.cpp$$ $rref log10.cpp$$ $rref sin.cpp$$ $rref sinh.cpp$$ $rref sqrt.cpp$$ $rref tan.cpp$$ $rref tanh.cpp$$ $tend $head Derivatives$$ Each of these functions satisfy a standard math function differential equation. Calculating derivatives using this differential equation is discussed for both $cref/forward/ForwardTheory/Standard Math Functions/$$ and $cref/reverse/ReverseTheory/Standard Math Functions/$$ mode. The exact form of the differential equation for each of these functions is listed below: $subhead acos$$ $latex \[ \begin{array}{lcr} \D{[ {\rm acos} (x) ]}{x} & = & - (1 - x * x)^{-1/2} \end{array} \] $$ $subhead asin$$ $latex \[ \begin{array}{lcr} \D{[ {\rm asin} (x) ]}{x} & = & (1 - x * x)^{-1/2} \end{array} \] $$ $subhead atan$$ $latex \[ \begin{array}{lcr} \D{[ {\rm atan} (x) ]}{x} & = & \frac{1}{1 + x^2} \end{array} \] $$ $subhead cos$$ $latex \[ \begin{array}{lcr} \D{[ \cos (x) ]}{x} & = & - \sin (x) \\ \D{[ \sin (x) ]}{x} & = & \cos (x) \end{array} \] $$ $subhead cosh$$ $latex \[ \begin{array}{lcr} \D{[ \cosh (x) ]}{x} & = & \sinh (x) \\ \D{[ \sin (x) ]}{x} & = & \cosh (x) \end{array} \] $$ $subhead exp$$ $latex \[ \begin{array}{lcr} \D{[ \exp (x) ]}{x} & = & \exp (x) \end{array} \] $$ $subhead log$$ $latex \[ \begin{array}{lcr} \D{[ \log (x) ]}{x} & = & \frac{1}{x} \end{array} \] $$ $subhead log10$$ This function is special in that it's derivatives are calculated using the relation $latex \[ \begin{array}{lcr} {\rm log10} (x) & = & \log(x) / \log(10) \end{array} \] $$ $subhead sin$$ $latex \[ \begin{array}{lcr} \D{[ \sin (x) ]}{x} & = & \cos (x) \\ \D{[ \cos (x) ]}{x} & = & - \sin (x) \end{array} \] $$ $subhead sinh$$ $latex \[ \begin{array}{lcr} \D{[ \sinh (x) ]}{x} & = & \cosh (x) \\ \D{[ \cosh (x) ]}{x} & = & \sinh (x) \end{array} \] $$ $subhead sqrt$$ $latex \[ \begin{array}{lcr} \D{[ {\rm sqrt} (x) ]}{x} & = & \frac{1}{2 {\rm sqrt} (x) } \end{array} \] $$ $subhead tan$$ $latex \[ \begin{array}{lcr} \D{[ \tan (x) ]}{x} & = & 1 + \tan (x)^2 \end{array} \] $$ $subhead tanh$$ $latex \[ \begin{array}{lcr} \D{[ \tanh (x) ]}{x} & = & 1 - \tanh (x)^2 \end{array} \] $$ $end ------------------------------------------------------------------------------- */ /*! \file std_math_ad.hpp Define AD standard math functions (using their Base versions) */ /*! \def CPPAD_STANDARD_MATH_UNARY_AD(Name, Op) Defines function Name with argument type AD and tape operation Op The macro defines the function x.Name() where x has type AD. It then uses this funciton to define Name(x) where x has type AD or VecAD_reference. If x is a variable, the tape unary operator Op is used to record the operation and the result is identified as correspoding to this operation; i.e., Name(x).taddr_ idendifies the operation and Name(x).tape_id_ identifies the tape. This macro is used to define AD versions of acos, asin, atan, cos, cosh, exp, fabs, log, sin, sinh, sqrt, tan, tanh. */ # define CPPAD_STANDARD_MATH_UNARY_AD(Name, Op) \ template \ inline AD Name(const AD &x) \ { return x.Name(); } \ template \ inline AD AD::Name (void) const \ { \ AD result; \ result.value_ = CppAD::Name(value_); \ CPPAD_ASSERT_UNKNOWN( Parameter(result) ); \ \ if( Variable(*this) ) \ { CPPAD_ASSERT_UNKNOWN( NumArg(Op) == 1 ); \ ADTape *tape = tape_this(); \ tape->Rec_.PutArg(taddr_); \ result.taddr_ = tape->Rec_.PutOp(Op); \ result.tape_id_ = tape->id_; \ } \ return result; \ } \ template \ inline AD Name(const VecAD_reference &x) \ { return Name( x.ADBase() ); } // BEGIN CppAD namespace namespace CppAD { CPPAD_STANDARD_MATH_UNARY_AD(acos, AcosOp) CPPAD_STANDARD_MATH_UNARY_AD(asin, AsinOp) CPPAD_STANDARD_MATH_UNARY_AD(atan, AtanOp) CPPAD_STANDARD_MATH_UNARY_AD(cos, CosOp) CPPAD_STANDARD_MATH_UNARY_AD(cosh, CoshOp) CPPAD_STANDARD_MATH_UNARY_AD(exp, ExpOp) CPPAD_STANDARD_MATH_UNARY_AD(fabs, AbsOp) CPPAD_STANDARD_MATH_UNARY_AD(log, LogOp) CPPAD_STANDARD_MATH_UNARY_AD(sin, SinOp) CPPAD_STANDARD_MATH_UNARY_AD(sinh, SinhOp) CPPAD_STANDARD_MATH_UNARY_AD(sqrt, SqrtOp) CPPAD_STANDARD_MATH_UNARY_AD(tan, TanOp) CPPAD_STANDARD_MATH_UNARY_AD(tanh, TanhOp) # if CPPAD_COMPILER_HAS_ERF // Error function is a special case template inline AD erf(const AD &x) { return x.erf(); } template inline AD AD::erf (void) const { AD result; result.value_ = CppAD::erf(value_); CPPAD_ASSERT_UNKNOWN( Parameter(result) ); if( Variable(*this) ) { CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 ); ADTape *tape = tape_this(); // arg[0] = argument to erf function tape->Rec_.PutArg(taddr_); // arg[1] = zero addr_t p = tape->Rec_.PutPar( Base(0) ); tape->Rec_.PutArg(p); // arg[2] = 2 / sqrt(pi) p = tape->Rec_.PutPar(Base( 1.0 / std::sqrt( std::atan(1.0) ) )); tape->Rec_.PutArg(p); // result.taddr_ = tape->Rec_.PutOp(ErfOp); result.tape_id_ = tape->id_; } return result; } template inline AD erf(const VecAD_reference &x) { return erf( x.ADBase() ); } # endif /*! Compute the log of base 10 of x where has type AD \tparam Base is the base type (different from base for log) for this AD type, see base_require. \param x is the argument for the log10 function. \result if the result is y, then \f$ x = 10^y \f$. */ template inline AD log10(const AD &x) { return CppAD::log(x) / CppAD::log( Base(10) ); } template inline AD log10(const VecAD_reference &x) { return CppAD::log(x.ADBase()) / CppAD::log( Base(10) ); } } # undef CPPAD_STANDARD_MATH_UNARY_AD # endif TMB/inst/include/cppad/local/integer.hpp0000644000176200001440000000546614536067013017643 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_INTEGER_INCLUDED # define CPPAD_INTEGER_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------ $begin Integer$$ $spell std VecAD CppAD namespace const bool $$ $index Integer$$ $index AD, convert to integer$$ $index convert, AD to integer$$ $section Convert From AD to Integer$$ $head Syntax$$ $icode%i% = Integer(%x%)%$$ $head Purpose$$ Converts from an AD type to the corresponding integer value. $head i$$ The result $icode i$$ has prototype $codei% int %i% %$$ $head x$$ $subhead Real Types$$ If the argument $icode x$$ has either of the following prototypes: $codei% const float %% &%x% const double %% &%x% %$$ the fractional part is dropped to form the integer value. For example, if $icode x$$ is 1.5, $icode i$$ is 1. In general, if $latex x \geq 0$$, $icode i$$ is the greatest integer less than or equal $icode x$$. If $latex x \leq 0$$, $icode i$$ is the smallest integer greater than or equal $icode x$$. $subhead Complex Types$$ If the argument $icode x$$ has either of the following prototypes: $codei% const std::complex %% &%x% const std::complex %% &%x% %$$ The result $icode i$$ is given by $codei% %i% = Integer(%x%.real()) %$$ $subhead AD Types$$ If the argument $icode x$$ has either of the following prototypes: $codei% const AD<%Base%> &%x% const VecAD<%Base%>::reference &%x% %$$ $icode Base$$ must support the $code Integer$$ function and the conversion has the same meaning as for $icode Base$$. $head Operation Sequence$$ The result of this operation is not an $cref/AD of Base/glossary/AD of Base/$$ object. Thus it will not be recorded as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Example$$ $children% example/integer.cpp %$$ The file $cref integer.cpp$$ contains an example and test of this operation. $end ------------------------------------------------------------------------------ */ namespace CppAD { template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION int Integer(const AD &x) { return Integer(x.value_); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION int Integer(const VecAD_reference &x) { return Integer( x.ADBase() ); } } # endif TMB/inst/include/cppad/local/limits.hpp0000644000176200001440000001113214536067013017472 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_LIMITS_INCLUDED # define CPPAD_LIMITS_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------ $begin limits$$ $spell std eps CppAD namespace const $$ $index limits, AD$$ $index AD, limits$$ $index epsilon, AD$$ $index limit, max$$ $index limit, min$$ $index limit, epsilon$$ $section Numeric Limits For an AD and Base Types$$ $head Syntax$$ $icode%eps% = numeric_limits<%Float%>::epsilon() %$$ $icode%min% = numeric_limits<%Float%>::min() %$$ $icode%max% = numeric_limits<%Float%>::max() %$$ $head Purpose$$ Obtain the value of some of the C++ standard numeric limits using the CppAD namespace version of $code numeric_limits$$. These are all functions and have the prototype $codei% %Float% numeric_limits<%Float%>::%fun%(%void%) %$$ where $icode fun$$ is $code epsilon$$, $code min$$, or $code max$$. $pre $$ Note that C++ standard specifies that Non-fundamental standard types, such as $codei%std::complex<%T%>%$$ shall not have specializations of $code std::numeric_limits$$; see Section 18.2 of ISO/IEC 14882:1998(E). $head Float$$ These functions are defined for all $codei%AD<%Base%>%$$, and for all corresponding $icode Base$$ types; see $icode Base$$ type $cref/limits/base_std_math/limits/$$. $head eps$$ The result $icode eps$$ is equal to machine epsilon and has prototype $codei% %Float% %eps% %$$ CppAD tests the value $icode eps$$ by checking that the following are true $codei% 1 != 1 + %eps% 1 == 1 + %eps% / 2 %$$ where all the values, and calculations, are done with the precision corresponding to $icode Float$$. $head min$$ The result $icode min$$ is equal to the minimum positive normalized value and has prototype $codei% %Float% %min% %$$ CppAD tests the value $icode min$$ by checking that the following are true $codei% abs( ((%min% / 100) * 100) / %min% - 1 ) > 3 * %eps% abs( ((%min% * 100) / (100 * (1 - %eps%)) / %min% - 1 ) < 3 * %eps% %$$ where all the values, and calculations, are done with the precision corresponding to $icode Float$$. $head max$$ The result $icode max$$ is equal to the maximum finite value and has prototype $codei% %Float% %max% %$$ CppAD tests the value $icode max$$ by checking that the following are true $codei% abs( ((%max% * 100) / 100) / %max% - 1 ) > 3 * %eps% abs( ((%max% / 100) * (100 * (1 - %eps%)) / %max% - 1 ) < 3 * %eps% %$$ where all the values, and calculations, are done with the precision corresponding to $icode Float$$. $head Example$$ $children% example/limits.cpp %$$ The file $cref limits.cpp$$ contains an example and test of these functions. $end ------------------------------------------------------------------------------ */ # include # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file limits.hpp File that defines CppAD numeric_limits for AD types */ /// Default value for all undefined numeric_limits types template class numeric_limits { public: /// machine epsilon static Float epsilon(void) { CPPAD_ASSERT_KNOWN( false, "numeric_limits::epsilon() is not specialized for this Float" ); return Float(0); } /// minimum positive normalized value static Float min(void) { CPPAD_ASSERT_KNOWN( false, "numeric_limits::min() is not specialized for this Float" ); return Float(0); } /// maximum finite value static Float max(void) { CPPAD_ASSERT_KNOWN( false, "numeric_limits::max() is not specialized for this Float" ); return Float(0); } }; /// Partial specialization that defines limits for for all AD types template class numeric_limits< AD > { public: /// machine epsilon static AD epsilon(void) { return AD( numeric_limits::epsilon() ); } /// minimum positive normalized value static AD min(void) { return AD( numeric_limits::min() ); } /// maximum finite value static AD max(void) { return AD( numeric_limits::max() ); } }; } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sin_op.hpp0000644000176200001440000001463414536067013017472 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SIN_OP_INCLUDED # define CPPAD_SIN_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sin_op.hpp Forward and reverse mode calculations for z = sin(x). */ /*! Compute forward mode Taylor coefficient for result of op = SinOp. The C++ source code corresponding to this operation is \verbatim z = sin(x) \endverbatim The auxillary result is \verbatim y = cos(x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_sin_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* s = taylor + i_z * cap_order; Base* c = s - cap_order; // rest of this routine is identical for the following cases: // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op. // (except that there is a sign difference for the hyperbolic case). size_t k; if( p == 0 ) { s[0] = sin( x[0] ); c[0] = cos( x[0] ); p++; } for(size_t j = p; j <= q; j++) { s[j] = Base(0); c[j] = Base(0); for(k = 1; k <= j; k++) { s[j] += Base(k) * x[k] * c[j-k]; c[j] -= Base(k) * x[k] * s[j-k]; } s[j] /= Base(j); c[j] /= Base(j); } } /*! Compute forward mode Taylor coefficient for result of op = SinOp. The C++ source code corresponding to this operation is \verbatim z = sin(x) \endverbatim The auxillary result is \verbatim y = cos(x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_sin_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* s = taylor + i_z * num_taylor_per_var; Base* c = s - num_taylor_per_var; // rest of this routine is identical for the following cases: // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op // (except that there is a sign difference for the hyperbolic case). size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { s[m+ell] = Base(q) * x[m + ell] * c[0]; c[m+ell] = - Base(q) * x[m + ell] * s[0]; for(size_t k = 1; k < q; k++) { s[m+ell] += Base(k) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell]; c[m+ell] -= Base(k) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell]; } s[m+ell] /= Base(q); c[m+ell] /= Base(q); } } /*! Compute zero order forward mode Taylor coefficient for result of op = SinOp. The C++ source code corresponding to this operation is \verbatim z = sin(x) \endverbatim The auxillary result is \verbatim y = cos(x) \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_sin_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* s = taylor + i_z * cap_order; // called z in documentation Base* c = s - cap_order; // called y in documentation s[0] = sin( x[0] ); c[0] = cos( x[0] ); } /*! Compute reverse mode partial derivatives for result of op = SinOp. The C++ source code corresponding to this operation is \verbatim z = sin(x) \endverbatim The auxillary result is \verbatim y = cos(x) \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_sin_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* s = taylor + i_z * cap_order; // called z in doc Base* ps = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* c = s - cap_order; // called y in documentation Base* pc = ps - nc_partial; // If ps is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(ps[i_d]); if( skip ) return; // rest of this routine is identical for the following cases: // reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op. size_t j = d; size_t k; while(j) { ps[j] /= Base(j); pc[j] /= Base(j); for(k = 1; k <= j; k++) { px[k] += ps[j] * Base(k) * c[j-k]; px[k] -= pc[j] * Base(k) * s[j-k]; ps[j-k] -= pc[j] * Base(k) * x[k]; pc[j-k] += ps[j] * Base(k) * x[k]; } --j; } px[0] += ps[0] * c[0]; px[0] -= pc[0] * s[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/hessian.hpp0000644000176200001440000001221014536067013017621 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_HESSIAN_INCLUDED # define CPPAD_HESSIAN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Hessian$$ $spell hes typename Taylor HesLuDet const $$ $index Hessian, driver$$ $index second, derivative$$ $index driver, Hessian$$ $section Hessian: Easy Driver$$ $head Syntax$$ $icode%hes% = %f%.Hessian(%x%, %w%) %$$ $icode%hes% = %f%.Hessian(%x%, %l%) %$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. The syntax above sets $icode hes$$ to the Hessian The syntax above sets $icode h$$ to the Hessian $latex \[ hes = \dpow{2}{x} \sum_{i=1}^m w_i F_i (x) \] $$ The routine $cref sparse_hessian$$ may be faster in the case where the Hessian is sparse. $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/Hessian Uses Forward/Hessian/Hessian Uses Forward/$$ below). $head x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ (see $cref/Vector/Hessian/Vector/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies that point at which to evaluate the Hessian. $head l$$ If the argument $icode l$$ is present, it has prototype $codei% size_t %l% %$$ and is less than $icode m$$, the dimension of the $cref/range/seq_property/Range/$$ space for $icode f$$. It specifies the component of $icode F$$ for which we are evaluating the Hessian. To be specific, in the case where the argument $icode l$$ is present, $latex \[ w_i = \left\{ \begin{array}{ll} 1 & i = l \\ 0 & {\rm otherwise} \end{array} \right. \] $$ $head w$$ If the argument $icode w$$ is present, it has prototype $codei% const %Vector% &%w% %$$ and size $latex m$$. It specifies the value of $latex w_i$$ in the expression for $icode h$$. $head hes$$ The result $icode hes$$ has prototype $codei% %Vector% %hes% %$$ (see $cref/Vector/Hessian/Vector/$$ below) and its size is $latex n * n$$. For $latex j = 0 , \ldots , n - 1 $$ and $latex \ell = 0 , \ldots , n - 1$$ $latex \[ hes [ j * n + \ell ] = \DD{ w^{\rm T} F }{ x_j }{ x_\ell } ( x ) \] $$ $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Base$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Hessian Uses Forward$$ After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After a call to $code Hessian$$, the zero order Taylor coefficients correspond to $icode%f%.Forward(0, %x%)%$$ and the other coefficients are unspecified. $head Example$$ $children% example/hessian.cpp% example/hes_lagrangian.cpp %$$ The routines $cref hessian.cpp$$ and $cref hes_lagrangian.cpp$$ are examples and tests of $code Hessian$$. They return $code true$$, if they succeed and $code false$$ otherwise. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template template Vector ADFun::Hessian(const Vector &x, size_t l) { size_t i, m = Range(); CPPAD_ASSERT_KNOWN( l < m, "Hessian: index i is not less than range dimension for f" ); Vector w(m); for(i = 0; i < m; i++) w[i] = Base(0); w[l] = Base(1); return Hessian(x, w); } template template Vector ADFun::Hessian(const Vector &x, const Vector &w) { size_t j; size_t k; size_t n = Domain(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( size_t(x.size()) == n, "Hessian: length of x not equal domain dimension for f" ); CPPAD_ASSERT_KNOWN( size_t(w.size()) == Range(), "Hessian: length of w not equal range dimension for f" ); // point at which we are evaluating the Hessian Forward(0, x); // define the return value Vector hes(n * n); // direction vector for calls to forward Vector u(n); for(j = 0; j < n; j++) u[j] = Base(0); // location for return values from Reverse Vector ddw(n * 2); // loop over forward directions for(j = 0; j < n; j++) { // evaluate partials of entire function w.r.t. j-th coordinate u[j] = Base(1); Forward(1, u); u[j] = Base(0); // evaluate derivative of partial corresponding to F_i ddw = Reverse(2, w); // return desired components for(k = 0; k < n; k++) hes[k * n + j] = ddw[k * 2 + 1]; } return hes; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/discrete_op.hpp0000644000176200001440000000660714536067013020504 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DISCRETE_OP_INCLUDED # define CPPAD_DISCRETE_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file discrete_op.hpp Forward mode for z = f(x) where f is piecewise constant. */ /*! forward mode Taylor coefficient for result of op = DisOp. The C++ source code corresponding to this operation is \verbatim z = f(x) \endverbatim where f is a piecewise constant function (and it's derivative is always calculated as zero). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param p is the lowest order Taylor coefficient that will be calculated. \param q is the highest order Taylor coefficient that will be calculated. \param r is the number of directions, for each order, that will be calculated (except for order zero wich only has one direction). \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param arg \a arg[0] \n is the index, in the order of the discrete functions defined by the user, for this discrete function. \n \n \a arg[1] variable index corresponding to the argument for this operator; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the taylor array. \par tpv We use the notation tpv = (cap_order-1) * r + 1 which is the number of Taylor coefficients per variable \param taylor \b Input: taylor [ arg[1] * tpv + 0 ] is the zero order Taylor coefficient corresponding to x. \n \b Output: if p == 0 taylor [ i_z * tpv + 0 ] is the zero order Taylor coefficient corresponding to z. For k = max(p, 1), ... , q, taylor [ i_z * tpv + (k-1)*r + 1 + ell ] is the k-th order Taylor coefficient corresponding to z (which is zero). \par Checked Assertions where op is the unary operator with one result: \li NumArg(op) == 2 \li NumRes(op) == 1 \li q < cap_order \li 0 < r */ template inline void forward_dis_op( size_t p , size_t q , size_t r , size_t i_z , const addr_t* arg , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DisOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DisOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( 0 < r ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + arg[1] * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; if( p == 0 ) { z[0] = discrete::eval(arg[0], x[0]); p++; } for(size_t ell = 0; ell < r; ell++) for(size_t k = p; k <= q; k++) z[ (k-1) * r + 1 + ell ] = Base(0); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/omp_max_thread.hpp0000644000176200001440000000520714536067013021166 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_OMP_MAX_THREAD_INCLUDED # define CPPAD_OMP_MAX_THREAD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-11 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin omp_max_thread$$ $spell alloc num omp OpenMp CppAD $$ $section OpenMP Parallel Setup$$ $head Deprecated$$ $index depreciated, omp_max_thread$$ $index omp_max_thread, depreciated$$ Use $cref/thread_alloc::parallel_setup/ta_parallel_setup/$$ to set the number of threads. $head Syntax$$ $codei%AD<%Base%>::omp_max_thread(%number%) %$$ $head Purpose$$ By default, for each $codei%AD<%Base%>%$$ class there is only one tape that records $cref/AD of Base/glossary/AD of Base/$$ operations. This tape is a global variable and hence it cannot be used by multiple OpenMP threads at the same time. The $code omp_max_thread$$ function is used to set the maximum number of OpenMP threads that can be active. In this case, there is a different tape corresponding to each $codei%AD<%Base%>%$$ class and thread pair. $head number$$ The argument $icode number$$ has prototype $codei% size_t %number% %$$ It must be greater than zero and specifies the maximum number of OpenMp threads that will be active at one time. $head Independent$$ Each call to $cref/Independent(x)/Independent/$$ creates a new $cref/active/glossary/Tape/Active/$$ tape. All of the operations with the corresponding variables must be preformed by the same OpenMP thread. This includes the corresponding call to $cref/f.Dependent(x,y)/Dependent/$$ or the $cref/ADFun f(x, y)/FunConstruct/Sequence Constructor/$$ during which the tape stops recording and the variables become parameters. $head Restriction$$ No tapes can be $cref/active/glossary/Tape/Active/$$ when this function is called. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template void AD::omp_max_thread(size_t number) { # ifdef _OPENMP thread_alloc::parallel_setup( number, omp_alloc::in_parallel, omp_alloc::get_thread_num ); # else CPPAD_ASSERT_KNOWN( number == 1, "omp_max_thread: number > 1 and _OPENMP is not defined" ); # endif parallel_ad(); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/sinh_op.hpp0000644000176200001440000001466214536067013017643 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SINH_OP_INCLUDED # define CPPAD_SINH_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sinh_op.hpp Forward and reverse mode calculations for z = sinh(x). */ /*! Compute forward mode Taylor coefficient for result of op = SinhOp. The C++ source code corresponding to this operation is \verbatim z = sinh(x) \endverbatim The auxillary result is \verbatim y = cosh(x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_sinh_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* s = taylor + i_z * cap_order; Base* c = s - cap_order; // rest of this routine is identical for the following cases: // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op // (except that there is a sign difference for hyperbolic case). size_t k; if( p == 0 ) { s[0] = sinh( x[0] ); c[0] = cosh( x[0] ); p++; } for(size_t j = p; j <= q; j++) { s[j] = Base(0); c[j] = Base(0); for(k = 1; k <= j; k++) { s[j] += Base(k) * x[k] * c[j-k]; c[j] += Base(k) * x[k] * s[j-k]; } s[j] /= Base(j); c[j] /= Base(j); } } /*! Compute forward mode Taylor coefficient for result of op = SinhOp. The C++ source code corresponding to this operation is \verbatim z = sinh(x) \endverbatim The auxillary result is \verbatim y = cosh(x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_sinh_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* s = taylor + i_z * num_taylor_per_var; Base* c = s - num_taylor_per_var; // rest of this routine is identical for the following cases: // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op // (except that there is a sign difference for the hyperbolic case). size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { s[m+ell] = Base(q) * x[m + ell] * c[0]; c[m+ell] = Base(q) * x[m + ell] * s[0]; for(size_t k = 1; k < q; k++) { s[m+ell] += Base(k) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell]; c[m+ell] += Base(k) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell]; } s[m+ell] /= Base(q); c[m+ell] /= Base(q); } } /*! Compute zero order forward mode Taylor coefficient for result of op = SinhOp. The C++ source code corresponding to this operation is \verbatim z = sinh(x) \endverbatim The auxillary result is \verbatim y = cosh(x) \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_sinh_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* s = taylor + i_z * cap_order; // called z in documentation Base* c = s - cap_order; // called y in documentation s[0] = sinh( x[0] ); c[0] = cosh( x[0] ); } /*! Compute reverse mode partial derivatives for result of op = SinhOp. The C++ source code corresponding to this operation is \verbatim z = sinh(x) \endverbatim The auxillary result is \verbatim y = cosh(x) \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_sinh_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* s = taylor + i_z * cap_order; // called z in doc Base* ps = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* c = s - cap_order; // called y in documentation Base* pc = ps - nc_partial; // If ps is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(ps[i_d]); if( skip ) return; // rest of this routine is identical for the following cases: // reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op. size_t j = d; size_t k; while(j) { ps[j] /= Base(j); pc[j] /= Base(j); for(k = 1; k <= j; k++) { px[k] += ps[j] * Base(k) * c[j-k]; px[k] += pc[j] * Base(k) * s[j-k]; ps[j-k] += pc[j] * Base(k) * x[k]; pc[j-k] += ps[j] * Base(k) * x[k]; } --j; } px[0] += ps[0] * c[0]; px[0] += pc[0] * s[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/var2par.hpp0000644000176200001440000000375414536067013017561 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_VAR2PAR_INCLUDED # define CPPAD_VAR2PAR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------ $begin Var2Par$$ $spell var const $$ $index Var2Par$$ $index variable, convert to parameter$$ $index parameter, convert from variable$$ $index value_, obtain during taping$$ $section Convert an AD Variable to a Parameter$$ $head Syntax$$ $icode%y% = Var2Par(%x%)%$$ $head Purpose$$ Returns a $cref/parameter/glossary/Parameter/$$ $icode y$$ with the same value as the $cref/variable/glossary/Variable/$$ $icode x$$. $head x$$ The argument $icode x$$ has prototype $codei% const AD<%Base%> &x %$$ The argument $icode x$$ may be a variable or parameter. $head y$$ The result $icode y$$ has prototype $codei% AD<%Base%> &y %$$ The return value $icode y$$ will be a parameter. $head Example$$ $children% example/var2par.cpp %$$ The file $cref var2par.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------ */ // BEGIN CppAD namespace namespace CppAD { template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION AD Var2Par(const AD &x) { AD y(x.value_); return y; } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION AD Var2Par(const VecAD_reference &x) { AD y(x.ADBase()); y.id_ = 0; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/test_vector.hpp0000644000176200001440000001012614536067013020534 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_TEST_VECTOR_INCLUDED # define CPPAD_TEST_VECTOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin test_vector$$ $spell ifdef undef Microsofts CppADvector hpp std endif ublas Dir valarray stdvector $$ $index CPPAD_TEST_VECTOR$$ $index vector, test$$ $index test, vector$$ $section Choosing The Vector Testing Template Class$$ $head Deprecated 2012-07-03$$ $index deprecated, test vector$$ The $code CPPAD_TEST_VECTOR$$ macro has been deprecated, use $cref/CPPAD_TESTVECTOR/testvector/$$ instead. $head Syntax$$ $codei%CPPAD_TEST_VECTOR<%Scalar%> %$$ $head Introduction$$ Many of the CppAD $cref/examples/example/$$ and tests use the $code CPPAD_TEST_VECTOR$$ template class to pass information. The default definition for this template class is $cref/CppAD::vector/CppAD_vector/$$. $head MS Windows$$ The include path for boost is not defined in the Windows project files. If we are using Microsofts compiler, the following code overrides the setting of $code CPPAD_BOOSTVECTOR$$: $codep */ // The next 7 lines are C++ source code. # ifdef _MSC_VER # if CPPAD_BOOSTVECTOR # undef CPPAD_BOOSTVECTOR # define CPPAD_BOOSTVECTOR 0 # undef CPPAD_CPPADVECTOR # define CPPAD_CPPADVECTOR 1 # endif # endif /* $$ $head CppAD::vector$$ By default $code CPPAD_CPPADVECTOR$$ is true and $code CPPAD_TEST_VECTOR$$ is defined by the following source code $codep */ // The next 3 line are C++ source code. # if CPPAD_CPPADVECTOR # define CPPAD_TEST_VECTOR CppAD::vector # endif /* $$ If you specify $code --with-eigenvector$$ on the $cref/configure/auto_tools/Configure/$$ command line, $code CPPAD_EIGENVECTOR$$ is true. This vector type cannot be supported by $code CPPAD_TEST_VECTOR$$ (use $cref/CPPAD_TESTVECTOR/testvector/$$ for this support) so $code CppAD::vector$$ is used in this case $codep */ // The next 3 line are C++ source code. # if CPPAD_EIGENVECTOR # define CPPAD_TEST_VECTOR CppAD::vector # endif /* $$ $head std::vector$$ If you specify $code --with-stdvector$$ on the $cref/configure/auto_tools/Configure/$$ command line during CppAD installation, $code CPPAD_STDVECTOR$$ is true and $code CPPAD_TEST_VECTOR$$ is defined by the following source code $codep */ // The next 4 lines are C++ source code. # if CPPAD_STDVECTOR # include # define CPPAD_TEST_VECTOR std::vector # endif /* $$ In this case CppAD will use $code std::vector$$ for its examples and tests. Use of $code CppAD::vector$$, $code std::vector$$, and $code std::valarray$$ with CppAD is always tested to some degree. Specifying $code --with-stdvector$$ will increase the amount of $code std::vector$$ testing. $head boost::numeric::ublas::vector$$ If you specify a value for $icode boost_dir$$ on the configure command line during CppAD installation, $code CPPAD_BOOSTVECTOR$$ is true and $code CPPAD_TEST_VECTOR$$ is defined by the following source code $codep */ // The next 4 lines are C++ source code. # if CPPAD_BOOSTVECTOR # include # define CPPAD_TEST_VECTOR boost::numeric::ublas::vector # endif /* $$ In this case CppAD will use Ublas vectors for its examples and tests. Use of $code CppAD::vector$$, $code std::vector$$, and $code std::valarray$$ with CppAD is always tested to some degree. Specifying $icode boost_dir$$ will increase the amount of Ublas vector testing. $head CppADvector Deprecated 2007-07-28$$ The preprocessor symbol $code CppADvector$$ is defined to have the same value as $code CPPAD_TEST_VECTOR$$ but its use is deprecated: $codep */ # define CppADvector CPPAD_TEST_VECTOR /* $$ $end ------------------------------------------------------------------------ */ # endif TMB/inst/include/cppad/local/kasper.hpp0000644000176200001440000004103514536067013017463 0ustar liggesusersCppAD::vector tp_; /* Vector of tape entries */ CppAD::vector var2op_; /* Get operator (index) that produced the given var as result */ CppAD::vector op_mark_; /* Mark operators that must be computed */ CppAD::vector > colpattern; CppAD::vector arg_mark_; /* op_arg_rec_ contains argument pointers. Need vector of the same length (op_arg_rec_.size()) containing bool. Call this vector "arg_mark_". Need to be able to lookup "arg_mark_[arg]" where arg is addr_t*. We have to first convert pointer to index: index=addr_t(op_arg-op_arg_rec_.data()); Then do the lookup arg_mark_[index]; */ CppAD::vector user_region_; /* Vector of same length as tp_ (tape_points) for which user_region[i] is true iff tp_[i].op is either "UserOp" or one of "Usr**" operators. */ CppAD::vector user_region_mark_; /* user_region_mark_[i] is marked if the i'th tape point belongs to an already marked user region. */ CppAD::vector constant_tape_point_; /* Vector of same length as tp_ (tape_points) that marks all tape_points that only depend on fixed effects. */ /* Helper function to print std::vector */ template void vprint(const std::vector& v) { Rcout << "["; size_t last = v.size() - 1; for(size_t i = 0; i < v.size(); ++i) { Rcout << v[i]; if (i != last) Rcout << ", "; } Rcout << "]"; Rcout << "\n"; } /* Helper function for markArgs */ void markOpField( //std::ostream &os , void* os, const char *leader, //const Type &value, const addr_t* op_arg, size_t width ){ addr_t index=addr_t(op_arg-play_.op_arg_rec_.data()); arg_mark_[index]=true; } bool isDepArg(const addr_t* op_arg){ addr_t index=addr_t(op_arg-play_.op_arg_rec_.data()); return arg_mark_[index]; } void mark_tape_point_args(size_t index, size_t mark){ tape_point tp1=tp_[index]; tape_point tp2=tp_[index+1]; const addr_t* op_arg; op_arg=tp1.op_arg; int numarg=tp2.op_arg - op_arg; for(int i=0;iGetTxt(ind[2]) << "\""; if( ind[0] & 2 ) markOpField(os, " v=", &ind[3], ncol); //else markOpField(os, " p=", Rec->GetPar(ind[3]), ncol); //os << "after=\"" << Rec->GetTxt(ind[4]) << "\""; break; case BeginOp: case EndOp: case InvOp: case UsrrvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 ); break; case DisOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); { //const char* name = discrete::name(ind[0]); //markOpField(os, " f=", name, ncol); markOpField(os, " x=", &ind[1], ncol); } break; case CExpOp: CPPAD_ASSERT_UNKNOWN(ind[1] != 0); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 ); if( ind[1] & 1 ) markOpField(os, " vl=", &ind[2], ncol); //else markOpField(os, " pl=", Rec->GetPar(ind[2]), ncol); if( ind[1] & 2 ) markOpField(os, " vr=", &ind[3], ncol); //else markOpField(os, " pr=", Rec->GetPar(ind[3]), ncol); if( ind[1] & 4 ) markOpField(os, " vt=", &ind[4], ncol); //else markOpField(os, " pt=", Rec->GetPar(ind[4]), ncol); if( ind[1] & 8 ) markOpField(os, " vf=", &ind[5], ncol); //else markOpField(os, " pf=", Rec->GetPar(ind[5]), ncol); break; default: CPPAD_ASSERT_UNKNOWN(0); } // size_t k; // if( NumRes(op) > 0 && (op != BeginOp) ) // { // for(k = 0; k < nfz; k++) // Rcout << "| fz[" << k << "]=" << fz[k]; // for(k = 0; k < nrz; k++) // Rcout << "| rz[" << k << "]=" << rz[k]; // } // Rcout << std::endl; } void my_next_reverse( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index, //vector& op_mark,vector& var2op,vector& tp, size_t mark) { // Call reverse_next until reach first relevant operator. First call will have op=EndOp. op_index--; while((op_mark_[op_index]!=mark) & (op_index>0))op_index--; // Set output values corresponding to the found operator op = tp_[op_index].op; op_arg = tp_[op_index].op_arg; op_index = tp_[op_index].op_index; var_index = tp_[op_index].var_index; // op is marked - update dependencies mark_tape_point_args(op_index,mark); } /* mark_tape_point_args_index ========================== Given a tape_point index. 1. Find all the arguments of this tape_point... 2. And, for each argument find the operators that created the argument (variable)... 3. And mark these operators. Note: New marked operators are placed on a stack (op_mark_index_) and are thus guarantied to be visited, along with children, grand children, etc. no matter which order we perform the search. We avoid placing the same node twice by maintaining a table of marked nodes (op_mark_) that quickly answers whether a given node is already in the stack. mark_user_tape_point_index ========================== One case is special: The UserOp, and all the codes that can come in between a "UserOp begin" and a "UserOp end", i.e. "Usr**". Whenever a "Usr**" is met we should mark everything between the two closest "UserOp begin" and "UserOp end". */ std::vector op_mark_index_; void mark_user_tape_point_index(size_t index, size_t mark){ if(user_region_mark_[index]!=mark){ /* is region already marked ? */ tape_point tp=tp_[index]; if(tp.op != UserOp){ /* Find nearest UserOp tags (begin/end) */ int i,j; i=index;while(tp_[i].op != UserOp)i--; j=index;while(tp_[j].op != UserOp)j++; /* Mark everything within UserOp begin/end tags - if not already marked */ for(int k=i;k<=j;k++){ user_region_mark_[k]=mark; if(op_mark_[k]!=mark){ /* FIXME: Many calls with FALSE for *all* k - why? */ op_mark_[k]=mark; op_mark_index_.push_back(k); } } } } } void mark_tape_point_args_index(size_t index, size_t mark){ tape_point tp1=tp_[index]; tape_point tp2=tp_[index+1]; const addr_t* op_arg; op_arg=tp1.op_arg; int numarg=tp2.op_arg - op_arg; for(int i=0;i::iterator it; for(it=op_mark_index_.begin();*it<=n;it++)sum++; colpattern[col].resize(sum); sum=0; for(it=op_mark_index_.begin();*it<=n;it++){colpattern[col][sum]=*it-1;sum++;} } void printTP(tape_point tp){ Base dummy[1000]; OpCode op=tp.op; const addr_t* arg=tp.op_arg; const Base* Z_tmp =dummy;//= Taylor + i_var * J; const Base* pZ_tmp =dummy;// Partial + i_var * K; printOp( Rcout, &play_, tp.op_index, tp.var_index, op, arg); Rcout << "\n"; } bool is_tape_point_constant(size_t index){ bool ok_index= (index<=tp_.size()-2); if(!ok_index) return false; tape_point tp1=tp_[index]; tape_point tp2=tp_[index+1]; const addr_t* op_arg; op_arg=tp1.op_arg; int numarg=tp2.op_arg - op_arg; // Handle the user operator special case if(tp1.op == UsrrvOp || tp1.op == UsrrpOp){ // Result of user atomic operation bool constant=true; size_t i=index; while(tp_[i].op != UserOp){ i--; constant = constant && constant_tape_point_[i]; if(tp_[i].op == UsrrvOp || tp_[i].op == UsrrpOp)break; } return constant; } if(numarg==0)return false; // E.g. begin or end operators bool ans=true; int from = 0; if (tp1.op == CSumOp) { from = 3; // Skip arg[0], arg[1], arg[2] } for(int i=from; i Partial; void my_init(vector keepcol){ Partial.extend(num_var_tape_ * 1); arg_mark_.resize(play_.op_arg_rec_.size()); for(size_t i=0;i &%x% const VecAD<%Base%>::reference &%x% %$$ $head y$$ The result $icode y$$ has type $codei% AD<%Base%> %y% %$$ It is equal to the operand $icode x$$. $head Operation Sequence$$ This is an AD of $icode Base$$ $cref/atomic operation/glossary/Operation/Atomic/$$ and hence is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Derivative$$ If $latex f$$ is a $cref/Base function/glossary/Base Function/$$, $latex \[ \D{[ + f(x) ]}{x} = \D{f(x)}{x} \] $$ $head Example$$ $children% example/unary_plus.cpp %$$ The file $cref unary_plus.cpp$$ contains an example and test of this operation. $end ------------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template inline AD AD::operator + (void) const { AD result(*this); return result; } template inline AD operator + (const VecAD_reference &right) { return right.ADBase(); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/declare_ad.hpp0000644000176200001440000001343014536067013020237 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DECLARE_AD_INCLUDED # define CPPAD_DECLARE_AD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # if CPPAD_HAS_CSTDINT_8_TO_64 # include # endif namespace CppAD { // The conditional expression operator enum type enum CompareOp { CompareLt, // less than CompareLe, // less than or equal CompareEq, // equal CompareGe, // greater than or equal CompareGt, // greater than CompareNe // not equal }; // simple typedefs typedef CPPAD_TAPE_ADDR_TYPE addr_t; typedef CPPAD_TAPE_ID_TYPE tape_id_t; // classes class sparse_jacobian_work; class sparse_hessian_work; template class AD; template class ADFun; template class ADTape; template class atomic_base; template class discrete; template class player; template class recorder; template class VecAD; template class VecAD_reference; // functions with one VecAD argument template bool Parameter (const VecAD &u); template bool Variable (const VecAD &u); // functions with one AD argument template int Integer (const AD &u); template bool Parameter (const AD &u); template bool Variable (const AD &u); template bool IdenticalZero (const AD &u); template bool IdenticalOne (const AD &u); template bool IdenticalPar (const AD &u); template bool LessThanZero (const AD &u); template bool LessThanOrZero (const AD &u); template bool GreaterThanZero (const AD &u); template bool GreaterThanOrZero (const AD &u); template AD Var2Par (const AD &u); template AD abs (const AD &u); template AD acos (const AD &u); template AD asin (const AD &u); template AD atan (const AD &u); template AD cos (const AD &u); template AD cosh (const AD &u); template AD exp (const AD &u); template AD log (const AD &u); template AD log10 (const AD &u); template AD sin (const AD &u); template AD sinh (const AD &u); template AD sqrt (const AD &u); template AD tan (const AD &u); // arithematic operators template AD operator + ( const AD &left, const AD &right); template AD operator - ( const AD &left, const AD &right); template AD operator * ( const AD &left, const AD &right); template AD operator / ( const AD &left, const AD &right); // comparison operators template bool operator < ( const AD &left, const AD &right); template bool operator <= ( const AD &left, const AD &right); template bool operator > ( const AD &left, const AD &right); template bool operator >= ( const AD &left, const AD &right); template bool operator == ( const AD &left, const AD &right); template bool operator != ( const AD &left, const AD &right); // pow template AD pow ( const AD &x, const AD &y); // NearEqual template bool NearEqual( const AD &x, const AD &y, const Base &r, const Base &a); template bool NearEqual( const Base &x, const AD &y, const Base &r, const Base &a); template bool NearEqual( const AD &x, const Base &y, const Base &r, const Base &a); // CondExpOp template AD CondExpOp ( enum CompareOp cop , const AD &left , const AD &right , const AD &trueCase , const AD &falseCase ); // IdenticalEqualPar template bool IdenticalEqualPar (const AD &u, const AD &v); // EqualOpSeq template bool EqualOpSeq (const AD &u, const AD &v); // PrintFor template void PrintFor( const AD& flag , const char* before , const AD& var , const char* after ); // Value template Base Value(const AD &x); // Pow function template AD pow (const AD &x, const AD &y); // input operator template std::istream& operator >> (std::istream &is, AD &x); // output operator template std::ostream& operator << (std::ostream &os, const AD &x); template std::ostream& operator << (std::ostream &os, const VecAD_reference &e); template std::ostream& operator << (std::ostream &os, const VecAD &vec); } # endif TMB/inst/include/cppad/local/ordered.hpp0000644000176200001440000000546214536067013017626 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ORDERED_INCLUDED # define CPPAD_ORDERED_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file ordered.hpp Check and AD values ordering properties relative to zero. */ // GreaterThanZero ============================================================ /*! Check if an AD is greater than zero. \param x value we are checking. \return returns true iff the \c x is greater than zero. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool GreaterThanZero(const AD &x) { return GreaterThanZero(x.value_); } // GreaterThanOrZero ========================================================= /*! Check if an AD is greater than or equal zero. \param x value we are checking. \return returns true iff the \c x is greater than or equal zero. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool GreaterThanOrZero(const AD &x) { return GreaterThanOrZero(x.value_); } // LessThanZero ============================================================ /*! Check if an AD is less than zero. \param x value we are checking. \return returns true iff the \c x is less than zero. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool LessThanZero(const AD &x) { return LessThanZero(x.value_); } // LessThanOrZero ========================================================= /*! Check if an AD is less than or equal zero. \param x value we are checking. \return returns true iff the \c x is less than or equal zero. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool LessThanOrZero(const AD &x) { return LessThanOrZero(x.value_); } // abs_geq ========================================================= /*! Check if absolute value of one AD is greater or equal another. \param x value we are checking if it is greater than or equal other. \param y value we are checking if it is less than other. \return returns true iff the absolute value of \c x is greater than or equal absolute value of \c y. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool abs_geq(const AD& x, const AD& y) { return abs_geq(x.value_, y.value_); } // ============================================================================ } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sqrt_op.hpp0000644000176200001440000001207114536067013017663 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SQRT_OP_INCLUDED # define CPPAD_SQRT_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sqrt_op.hpp Forward and reverse mode calculations for z = sqrt(x). */ /*! Compute forward mode Taylor coefficient for result of op = SqrtOp. The C++ source code corresponding to this operation is \verbatim z = sqrt(x) \endverbatim \copydetails forward_unary1_op */ template inline void forward_sqrt_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; size_t k; if( p == 0 ) { z[0] = sqrt( x[0] ); p++; } for(size_t j = p; j <= q; j++) { CPPAD_ASSERT_KNOWN( x[0] != Base(0), "Forward: attempt to take derivatve of square root of zero" ) z[j] = Base(0); for(k = 1; k < j; k++) z[j] -= Base(k) * z[k] * z[j-k]; z[j] /= Base(j); z[j] += x[j] / Base(2); z[j] /= z[0]; } } /*! Multiple direction forward mode Taylor coefficient for op = SqrtOp. The C++ source code corresponding to this operation is \verbatim z = sqrt(x) \endverbatim \copydetails forward_unary1_op_dir */ template inline void forward_sqrt_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* z = taylor + i_z * num_taylor_per_var; Base* x = taylor + i_x * num_taylor_per_var; CPPAD_ASSERT_KNOWN( x[0] != Base(0), "Forward: attempt to take derivatve of square root of zero" ) size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { z[m+ell] = Base(0); for(size_t k = 1; k < q; k++) z[m+ell] -= Base(k) * z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell]; z[m+ell] /= Base(q); z[m+ell] += x[m+ell] / Base(2); z[m+ell] /= z[0]; } } /*! Compute zero order forward mode Taylor coefficient for result of op = SqrtOp. The C++ source code corresponding to this operation is \verbatim z = sqrt(x) \endverbatim \copydetails forward_unary1_op_0 */ template inline void forward_sqrt_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; z[0] = sqrt( x[0] ); } /*! Compute reverse mode partial derivatives for result of op = SqrtOp. The C++ source code corresponding to this operation is \verbatim z = sqrt(x) \endverbatim \copydetails reverse_unary1_op */ template inline void reverse_sqrt_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to result const Base* z = taylor + i_z * cap_order; Base* pz = partial + i_z * nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; CPPAD_ASSERT_KNOWN( z[0] != Base(0), "Reverse: attempt to take derivatve of square root of zero" ) // number of indices to access size_t j = d; size_t k; while(j) { // scale partial w.r.t. z[j] pz[j] /= z[0]; pz[0] -= pz[j] * z[j]; px[j] += pz[j] / Base(2); for(k = 1; k < j; k++) pz[k] -= pz[j] * z[j-k]; --j; } px[0] += pz[0] / (Base(2) * z[0]); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/undef.hpp0000644000176200001440000000747614536067013017312 0ustar liggesusers// $Id:$ # ifndef CPPAD_UNDEF_INCLUDED # define CPPAD_UNDEF_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------- Preprecessor definitions that presist after cppad/cppad.hpp is included: # undef CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL used by CPPAD_USER_ATOMIC # undef CPPAD_ASSERT_KNOWN needed by cppad_ipopt # undef CPPAD_ASSERT_UNKNOWN needed by cppad_ipopt # undef CPPAD_HASH_TABLE_SIZE used by test_more/optimize.cpp # undef EIGEN_MATRIXBASE_PLUGIN example use of Eigen with CppAD # undef CPPAD_BOOL_BINARY in user api # undef CPPAD_BOOL_UNARY in user api # undef CPPAD_DISCRETE_FUNCTION in user api # undef CPPAD_EIGENVECTOR in user api # undef CPPAD_COMPILER_HAS_ERF in user api # undef CPPAD_INTERNAL_SPARSE_SET in user api # undef CPPAD_MAX_NUM_THREADS in user api # undef CPPAD_NULL in user api # undef CPPAD_PACKAGE_STRING in user api # undef CPPAD_TAPE_ADDR_TYPE in user api # undef CPPAD_TAPE_ID_TYPE in user api # undef CPPAD_TESTVECTOR in user api # undef CPPAD_TRACK_COUNT in deprecated api # undef CPPAD_TRACK_DEL_VEC in deprecated api # undef CPPAD_TRACK_EXTEND in deprecated api # undef CPPAD_TRACK_NEW_VEC in deprecated api # undef CPPAD_USER_ATOMIC in deprecated api # undef CPPAD_TEST_VECTOR deprecated verssion of CPPAD_TESTVECTOR # undef CppADCreateBinaryBool deprecated version of CPPAD_BOOL_BINARY # undef CppADCreateDiscrete deprecated version of CPPAD_DISCRETE_FUNCTION # undef CppADCreateUnaryBool deprecated version of CPPAD_BOOL_UNARY # undef CppADTrackCount deprecated version of CPPAD_TRACK_COUNT # undef CppADTrackDelVec deprecated version of CPPAD_TRACK_DEL_VEC # undef CppADTrackExtend deprecated version of CPPAD_TRACK_EXTEND # undef CppADTrackNewVec deprecated version of CPPAD_TRACK_NEW_VEC # undef CppADvector deprecated version of CPPAD_TEST_VECTOR // for conditional testing when implicit conversion is not present # undef CPPAD_IMPLICIT_CTOR_FROM_ANY_TYPE ----------------------------------------------------------------------------- */ // Preprecessor definitions that do not presist # undef CPPAD_ASSERT_NARG_NRES # undef CPPAD_ASSERT_NOT_PARALLEL # undef CPPAD_ASSERT_ARG_BEFORE_RESULT # undef CPPAD_BOOSTVECTOR # undef CPPAD_COND_EXP # undef CPPAD_COND_EXP_BASE_REL # undef CPPAD_COND_EXP_REL # undef CPPAD_CPPADVECTOR # undef CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR # undef CPPAD_FOLD_ASSIGNMENT_OPERATOR # undef CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR # undef CPPAD_FOR_JAC_SWEEP_TRACE # undef CPPAD_HAS_COLPACK # undef CPPAD_HAS_CSTDINT_8_TO_64 # undef CPPAD_HAS_RVALUE # undef CPPAD_HAS_HIGH_RESOLUTION_CLOCK # undef CPPAD_HAS_GETTIMEOFDAY # undef CPPAD_HAS_NULLPTR # undef CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION # undef CPPAD_MAX_NUM_CAPACITY # undef CPPAD_MIN_DOUBLE_CAPACITY # undef CPPAD_OP_CODE_TYPE # undef CPPAD_REVERSE_SWEEP_TRACE # undef CPPAD_REV_HES_SWEEP_TRACE # undef CPPAD_REV_JAC_SWEEP_TRACE # undef CPPAD_SIZE_T_NOT_UNSIGNED_INT # undef CPPAD_STANDARD_MATH_UNARY # undef CPPAD_STANDARD_MATH_UNARY_AD # undef CPPAD_STDVECTOR # undef CPPAD_TRACE_CAPACITY # undef CPPAD_TRACE_THREAD # undef CPPAD_TRACK_DEBUG # undef CPPAD_USER_MACRO # undef CPPAD_USER_MACRO_ONE # undef CPPAD_USER_MACRO_TWO # undef CPPAD_VEC_AD_COMPUTED_ASSIGNMENT # endif TMB/inst/include/cppad/local/fun_construct.hpp0000644000176200001440000003342414536067013021075 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FUN_CONSTRUCT_INCLUDED # define CPPAD_FUN_CONSTRUCT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin FunConstruct$$ $spell alloc num Jac bool taylor var ADvector const Jacobian $$ $spell $$ $section Construct an ADFun Object and Stop Recording$$ $index ADFun, construct$$ $index construct, ADFun$$ $index tape, stop recording$$ $index recording, stop tape$$ $head Syntax$$ $codei%ADFun<%Base%> %f%, %g% %$$ $codei%ADFun<%Base%> %f%(%x%, %y%) %$$ $icode%g% = %f% %$$ $head Purpose$$ The $codei%AD<%Base%>%$$ object $icode f$$ can store an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. It can then be used to calculate derivatives of the corresponding $cref/AD function/glossary/AD Function/$$ $latex \[ F : B^n \rightarrow B^m \] $$ where $latex B$$ is the space corresponding to objects of type $icode Base$$. $head x$$ If the argument $icode x$$ is present, it has prototype $codei% const %VectorAD% &%x% %$$ It must be the vector argument in the previous call to $cref Independent$$. Neither its size, or any of its values, are allowed to change between calling $codei% Independent(%x%) %$$ and $codei% ADFun<%Base%> %f%(%x%, %y%) %$$ $head y$$ If the argument $icode y$$ is present, it has prototype $codei% const %VectorAD% &%y% %$$ The sequence of operations that map $icode x$$ to $icode y$$ are stored in the ADFun object $icode f$$. $head VectorAD$$ The type $icode VectorAD$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $codei%AD<%Base%>%$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Default Constructor$$ $index default, ADFun constructor$$ $index ADFun, default constructor$$ $index constructor, ADFun constructor$$ The default constructor $codei% ADFun<%Base%> %f% %$$ creates an $codei%AD<%Base%>%$$ object with no corresponding operation sequence; i.e., $codei% %f%.size_var() %$$ returns the value zero (see $cref/size_var/seq_property/size_var/$$). $head Sequence Constructor$$ $index sequence, ADFun constructor$$ $index ADFun, sequence constructor$$ $index constructor, ADFun sequence$$ The sequence constructor $codei% ADFun<%Base%> %f%(%x%, %y%) %$$ creates the $codei%AD<%Base%>%$$ object $icode f$$, stops the recording of AD of $icode Base$$ operations corresponding to the call $codei% Independent(%x%) %$$ and stores the corresponding operation sequence in the object $icode f$$. It then stores the zero order Taylor coefficients (corresponding to the value of $icode x$$) in $icode f$$. This is equivalent to the following steps using the default constructor: $list number$$ Create $icode f$$ with the default constructor $codei% ADFun<%Base%> %f%; %$$ $lnext Stop the tape and storing the operation sequence using $codei% %f%.Dependent(%x%, %y%); %$$ (see $cref Dependent$$). $lnext Calculate the zero order Taylor coefficients for all the variables in the operation sequence using $codei% %f%.Forward(%p%, %x_p%) %$$ with $icode p$$ equal to zero and the elements of $icode x_p$$ equal to the corresponding elements of $icode x$$ (see $cref Forward$$). $lend $head Copy Constructor$$ $index copy, ADFun constructor$$ $index ADFun, copy constructor$$ $index constructor, ADFun copy$$ It is an error to attempt to use the $codei%ADFun<%Base%>%$$ copy constructor; i.e., the following syntax is not allowed: $codei% ADFun<%Base%> %g%(%f%) %$$ where $icode f$$ is an $codei%ADFun<%Base%>%$$ object. Use its $cref/default constructor/FunConstruct/Default Constructor/$$ instead and its assignment operator. $head Assignment Operator$$ $index ADFun, assignment operator$$ $index assignment, ADFun operator$$ $index operator, ADFun assignment$$ The $codei%ADFun<%Base%>%$$ assignment operation $codei% %g% = %f% %$$ makes a copy of the operation sequence currently stored in $icode f$$ in the object $icode g$$. The object $icode f$$ is not affected by this operation and can be $code const$$. All of information (state) stored in $icode f$$ is copied to $icode g$$ and any information originally in $icode g$$ is lost. $subhead Taylor Coefficients$$ The Taylor coefficient information currently stored in $icode f$$ (computed by $cref/f.Forward/Forward/$$) is copied to $icode g$$. Hence, directly after this operation $codei% %g%.size_order() == %f%.size_order() %$$ $subhead Sparsity Patterns$$ The forward Jacobian sparsity pattern currently stored in $icode f$$ (computed by $cref/f.ForSparseJac/ForSparseJac/$$) is copied to $icode g$$. Hence, directly after this operation $codei% %g%.size_forward_bool() == %f%.size_forward_bool() %g%.size_forward_set() == %f%.size_forward_set() %$$ $head Parallel Mode$$ $index parallel, ADFun$$ $index ADFun, parallel$$ The call to $code Independent$$, and the corresponding call to $codei% ADFun<%Base%> %f%( %x%, %y%) %$$ or $codei% %f%.Dependent( %x%, %y%) %$$ or $cref abort_recording$$, must be preformed by the same thread; i.e., $cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same. $head Example$$ $subhead Sequence Constructor$$ The file $cref independent.cpp$$ contains an example and test of the sequence constructor. It returns true if it succeeds and false otherwise. $subhead Default Constructor$$ The files $cref fun_check.cpp$$ and $cref hes_lagrangian.cpp$$ contain an examples and tests using the default constructor. They return true if they succeed and false otherwise. $children% example/fun_assign.cpp %$$ $subhead Assignment Operator$$ The file $cref fun_assign.cpp$$ contains an example and test of the $codei%ADFun<%Base%>%$$ assignment operator. It returns true if it succeeds and false otherwise. $end ---------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file fun_construct.hpp ADFun function constructors and assignment operator. */ /*! ADFun default constructor The C++ syntax for this operation is \verbatim ADFun f \endverbatim An empty ADFun object is created. The Dependent member function, or the ADFun assingment operator, can then be used to put an operation sequence in this ADFun object. \tparam Base is the base for the recording that can be stored in this ADFun object; i.e., operation sequences that were recorded using the type \c AD. */ template ADFun::ADFun(void) : has_been_optimized_(false), check_for_nan_(true) , compare_change_count_(1), compare_change_number_(0), compare_change_op_index_(0), num_var_tape_(0) { } /*! ADFun assignment operator The C++ syntax for this operation is \verbatim g = f \endverbatim where \c g and \c f are ADFun ADFun objects. A copy of the the operation sequence currently stored in \c f is placed in this ADFun object (called \c g above). Any information currently stored in this ADFun object is lost. \tparam Base is the base for the recording that can be stored in this ADFun object; i.e., operation sequences that were recorded using the type \c AD. \param f ADFun object containing the operation sequence to be copied. */ template void ADFun::operator=(const ADFun& f) { size_t m = f.Range(); size_t n = f.Domain(); size_t i; // go through member variables in ad_fun.hpp order // // size_t objects has_been_optimized_ = f.has_been_optimized_; check_for_nan_ = f.check_for_nan_; compare_change_count_ = f.compare_change_count_; compare_change_number_ = f.compare_change_number_; compare_change_op_index_ = f.compare_change_op_index_; num_order_taylor_ = f.num_order_taylor_; cap_order_taylor_ = f.cap_order_taylor_; num_direction_taylor_ = f.num_direction_taylor_; num_var_tape_ = f.num_var_tape_; // // CppAD::vector objects ind_taddr_.resize(n); ind_taddr_ = f.ind_taddr_; dep_taddr_.resize(m); dep_taddr_ = f.dep_taddr_; dep_parameter_.resize(m); dep_parameter_ = f.dep_parameter_; // // pod_vector objects taylor_ = f.taylor_; cskip_op_ = f.cskip_op_; load_op_ = f.load_op_; // // player play_ = f.play_; // // sparse_pack for_jac_sparse_pack_.resize(0, 0); size_t n_set = f.for_jac_sparse_pack_.n_set(); size_t end = f.for_jac_sparse_pack_.end(); if( n_set > 0 ) { CPPAD_ASSERT_UNKNOWN( n_set == num_var_tape_ ); CPPAD_ASSERT_UNKNOWN( f.for_jac_sparse_set_.n_set() == 0 ); for_jac_sparse_pack_.resize(n_set, end); for(i = 0; i < num_var_tape_ ; i++) { for_jac_sparse_pack_.assignment( i , i , f.for_jac_sparse_pack_ ); } } // // sparse_set for_jac_sparse_set_.resize(0, 0); n_set = f.for_jac_sparse_set_.n_set(); end = f.for_jac_sparse_set_.end(); if( n_set > 0 ) { CPPAD_ASSERT_UNKNOWN( n_set == num_var_tape_ ); CPPAD_ASSERT_UNKNOWN( f.for_jac_sparse_pack_.n_set() == 0 ); for_jac_sparse_set_.resize(n_set, end); for(i = 0; i < num_var_tape_; i++) { for_jac_sparse_set_.assignment( i , i , f.for_jac_sparse_set_ ); } } } /*! ADFun constructor from an operation sequence. The C++ syntax for this operation is \verbatim ADFun f(x, y) \endverbatim The operation sequence that started with the previous call \c Independent(x), and that ends with this operation, is stored in this \c ADFun object \c f. \tparam Base is the base for the recording that will be stored in the object \c f; i.e., the operations were recorded using the type \c AD. \tparam VectorAD is a simple vector class with elements of typea \c AD. \param x is the independent variable vector for this ADFun object. The domain dimension of this object will be the size of \a x. \param y is the dependent variable vector for this ADFun object. The range dimension of this object will be the size of \a y. \par Taylor Coefficients A zero order forward mode sweep is done, and if NDEBUG is not defined the resulting values for the depenedent variables are checked against the values in \a y. Thus, the zero order Taylor coefficients corresponding to the value of the \a x vector are stored in this ADFun object. */ template template ADFun::ADFun(const VectorAD &x, const VectorAD &y) { CPPAD_ASSERT_KNOWN( x.size() > 0, "ADFun: independent variable vector has size zero." ); CPPAD_ASSERT_KNOWN( Variable(x[0]), "ADFun: independent variable vector has been changed." ); ADTape* tape = AD::tape_ptr(x[0].tape_id_); CPPAD_ASSERT_KNOWN( tape->size_independent_ == size_t ( x.size() ), "ADFun: independent variable vector has been changed." ); size_t j, n = x.size(); # ifndef NDEBUG size_t i, m = y.size(); for(j = 0; j < n; j++) { CPPAD_ASSERT_KNOWN( size_t(x[j].taddr_) == (j+1), "ADFun: independent variable vector has been changed." ); CPPAD_ASSERT_KNOWN( x[j].tape_id_ == x[0].tape_id_, "ADFun: independent variable vector has been changed." ); } for(i = 0; i < m; i++) { CPPAD_ASSERT_KNOWN( CppAD::Parameter( y[i] ) | (y[i].tape_id_ == x[0].tape_id_) , "ADFun: dependent vector contains variables for" "\na different tape than the independent variables." ); } # endif // stop the tape and store the operation sequence Dependent(tape, y); // ad_fun.hpp member values not set by dependent check_for_nan_ = true; // allocate memory for one zero order taylor_ coefficient CPPAD_ASSERT_UNKNOWN( num_order_taylor_ == 0 ); CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 0 ); size_t c = 1; size_t r = 1; capacity_order(c, r); CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ == c ); CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == r ); // set zero order coefficients corresponding to indpendent variables CPPAD_ASSERT_UNKNOWN( n == ind_taddr_.size() ); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) ); CPPAD_ASSERT_UNKNOWN( size_t(x[j].taddr_) == (j+1) ); taylor_[ ind_taddr_[j] ] = x[j].value_; } // use independent variable values to fill in values for others CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() ); CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() ); forward0sweep(Rcout, false, n, num_var_tape_, &play_, cap_order_taylor_, taylor_.data(), cskip_op_.data(), load_op_, compare_change_count_, compare_change_number_, compare_change_op_index_ ); CPPAD_ASSERT_UNKNOWN( compare_change_count_ == 1 ); CPPAD_ASSERT_UNKNOWN( compare_change_number_ == 0 ); CPPAD_ASSERT_UNKNOWN( compare_change_op_index_ == 0 ); // now set the number of orders stored num_order_taylor_ = 1; # ifndef NDEBUG // on MS Visual Studio 2012, CppAD required in front of isnan ? for(i = 0; i < m; i++) if( taylor_[dep_taddr_[i]] != y[i].value_ || CppAD::isnan( y[i].value_ ) ) { using std::endl; std::ostringstream buf; buf << "A dependent variable value is not equal to " << "its tape evaluation value," << endl << "perhaps it is nan." << endl << "Dependent variable value = " << y[i].value_ << endl << "Tape evaluation value = " << taylor_[dep_taddr_[i]] << endl << "Difference = " << y[i].value_ - taylor_[dep_taddr_[i]] << endl ; CPPAD_ASSERT_KNOWN( 0, buf.str().c_str() ); } # endif } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/independent.hpp0000644000176200001440000001301214536067013020465 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_INDEPENDENT_INCLUDED # define CPPAD_INDEPENDENT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- $begin Independent$$ $spell op alloc num Cpp bool const var typename $$ $index Independent$$ $index start, recording$$ $index recording, start$$ $index variable, independent$$ $section Declare Independent Variables and Start Recording$$ $head Syntax$$ $codei%Independent(%x%) %$$ $codei%Independent(%x%, %abort_op_index%) %$$ $head Purpose$$ Start recording $cref/AD of Base/glossary/AD of Base/$$ operations with $icode x$$ as the independent variable vector. Once the $cref/operation sequence/glossary/Operation/Sequence/$$ is completed, it must be transferred to a function object; see below. $head Start Recording$$ An operation sequence recording is started by the commands $codei% Independent(%x%) Independent(%x%, %abort_op_index%) %$$ $head Stop Recording$$ The recording is stopped, and the operation sequence is transferred to the AD function object $icode f$$, using either the $cref/function constructor/FunConstruct/$$ $codei% ADFun<%Base%> %f%(%x%, %y%) %$$ or the $cref/dependent variable specifier/Dependent/$$ $codei% %f%.Dependent(%x%, %y%) %$$ The only other way to stop a recording is using $cref abort_recording$$. Between when the recording is started and when it stopped, we refer to the elements of $icode x$$, and the values that depend on the elements of $icode x$$, as $codei%AD<%Base%>%$$ variables. $head x$$ The vector $icode x$$ has prototype $codei% %VectorAD% &%x% %$$ (see $icode VectorAD$$ below). The size of the vector $icode x$$, must be greater than zero, and is the number of independent variables for this AD operation sequence. $head abort_op_index$$ $index abort_op_index$$ It specifies the operator index at which the execution is be aborted by calling the CppAD $cref/error handler/ErrorHandler/$$. When this error handler leads to an assert, the user can inspect the call stack to see the source code corresponding to this operator index; see $cref/purpose/compare_change/op_index/Purpose/$$. No abort will occur if $icode abort_op_index$$ is zero, of if $cref/NDEBUG/Faq/Speed/NDEBUG/$$ is defined. $head VectorAD$$ The type $icode VectorAD$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $codei%AD<%Base%>%$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Parallel Mode$$ $index parallel, Independent$$ $index Independent, parallel$$ The call to $code Independent$$, and the corresponding call to $codei% ADFun<%Base%> %f%( %x%, %y%) %$$ or $codei% %f%.Dependent( %x%, %y%) %$$ or $cref abort_recording$$, must be preformed by the same thread; i.e., $cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same. $head Example$$ $children% example/independent.cpp %$$ The file $cref independent.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { // --------------------------------------------------------------------------- template template void ADTape::Independent(VectorAD &x, size_t abort_op_index) { // check VectorAD is Simple Vector class with AD elements CheckSimpleVector< AD, VectorAD>(); // dimension of the domain space size_t n = x.size(); CPPAD_ASSERT_KNOWN( n > 0, "Indepdendent: the argument vector x has zero size" ); CPPAD_ASSERT_UNKNOWN( Rec_.num_var_rec() == 0 ); // set the abort index before doing anything else Rec_.set_abort_op_index(abort_op_index); // mark the beginning of the tape and skip the first variable index // (zero) because parameters use taddr zero CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1); Rec_.PutOp(BeginOp); Rec_.PutArg(0); // place each of the independent variables in the tape CPPAD_ASSERT_NARG_NRES(InvOp, 0, 1); size_t j; for(j = 0; j < n; j++) { // tape address for this independent variable x[j].taddr_ = Rec_.PutOp(InvOp); x[j].tape_id_ = id_; CPPAD_ASSERT_UNKNOWN( size_t(x[j].taddr_) == j+1 ); CPPAD_ASSERT_UNKNOWN( Variable(x[j] ) ); } // done specifying all of the independent variables size_independent_ = n; } template inline void Independent(VectorAD &x, size_t abort_op_index) { typedef typename VectorAD::value_type ADBase; typedef typename ADBase::value_type Base; CPPAD_ASSERT_KNOWN( ADBase::tape_ptr() == CPPAD_NULL, "Independent: cannot create a new tape because\n" "a previous tape is still active (for this thread).\n" "AD::abort_recording() would abort this previous recording." ); ADTape* tape = ADBase::tape_manage(tape_manage_new); tape->Independent(x, abort_op_index); } template inline void Independent(VectorAD &x) { size_t abort_op_index = 0; Independent(x, abort_op_index); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/cond_op.hpp0000644000176200001440000007672114536067013017631 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_COND_OP_INCLUDED # define CPPAD_COND_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file cond_op.hpp Forward, reverse, and sparse operations for conditional expressions. */ /*! Shared documentation for conditional expressions (not called). The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \param parameter For j = 0, 1, 2, 3, if y_j is a parameter, \a parameter [ arg[2 + j] ] is its value. \param cap_order number of columns in the matrix containing the Taylor coefficients. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. */ template inline void conditional_exp_op( size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order ) { // This routine is only for documentation, it should never be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Shared documentation for conditional expression sparse operations (not called). The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. */ template inline void sparse_conditional_exp_op( size_t i_z , const addr_t* arg , size_t num_par ) { // This routine is only for documentation, it should never be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Compute forward mode Taylor coefficients for op = CExpOp. The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \param parameter For j = 0, 1, 2, 3, if y_j is a parameter, \a parameter [ arg[2 + j] ] is its value. \param cap_order number of columns in the matrix containing the Taylor coefficients. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. \param p is the lowest order of the Taylor coefficient of z that we are computing. \param q is the highest order of the Taylor coefficient of z that we are computing. \param taylor \b Input: For j = 0, 1, 2, 3 and k = 0 , ... , q, if y_j is a variable then taylor [ arg[2+j] * cap_order + k ] is the k-th order Taylor coefficient corresponding to y_j. \n \b Input: taylor [ i_z * cap_order + k ] for k = 0 , ... , p-1, is the k-th order Taylor coefficient corresponding to z. \n \b Output: taylor [ i_z * cap_order + k ] for k = p , ... , q, is the k-th order Taylor coefficient corresponding to z. */ template inline void forward_cond_op( size_t p , size_t q , size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , Base* taylor ) { Base y_0, y_1, y_2, y_3; Base zero(0); Base* z = taylor + i_z * cap_order; CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast (CompareNe) ); CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); if( arg[1] & 1 ) { y_0 = taylor[ arg[2] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); y_0 = parameter[ arg[2] ]; } if( arg[1] & 2 ) { y_1 = taylor[ arg[3] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); y_1 = parameter[ arg[3] ]; } if( p == 0 ) { if( arg[1] & 4 ) { y_2 = taylor[ arg[4] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par ); y_2 = parameter[ arg[4] ]; } if( arg[1] & 8 ) { y_3 = taylor[ arg[5] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par ); y_3 = parameter[ arg[5] ]; } z[0] = CondExpOp( CompareOp( arg[0] ), y_0, y_1, y_2, y_3 ); p++; } for(size_t d = p; d <= q; d++) { if( arg[1] & 4 ) { y_2 = taylor[ arg[4] * cap_order + d]; } else y_2 = zero; if( arg[1] & 8 ) { y_3 = taylor[ arg[5] * cap_order + d]; } else y_3 = zero; z[d] = CondExpOp( CompareOp( arg[0] ), y_0, y_1, y_2, y_3 ); } return; } /*! Multiple directions forward mode Taylor coefficients for op = CExpOp. The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \param parameter For j = 0, 1, 2, 3, if y_j is a parameter, \a parameter [ arg[2 + j] ] is its value. \param cap_order number of columns in the matrix containing the Taylor coefficients. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. \param q is order of the Taylor coefficient of z that we are computing. \param r is the number of Taylor coefficient directions that we are computing. \par tpv We use the notation tpv = (cap_order-1) * r + 1 which is the number of Taylor coefficients per variable \param taylor \b Input: For j = 0, 1, 2, 3, k = 1, ..., q, if y_j is a variable then taylor [ arg[2+j] * tpv + 0 ] is the zero order Taylor coefficient corresponding to y_j and taylor [ arg[2+j] * tpv + (k-1)*r+1+ell is its k-th order Taylor coefficient in the ell-th direction. \n \b Input: For j = 0, 1, 2, 3, k = 1, ..., q-1, taylor [ i_z * tpv + 0 ] is the zero order Taylor coefficient corresponding to z and taylor [ i_z * tpv + (k-1)*r+1+ell is its k-th order Taylor coefficient in the ell-th direction. \n \b Output: taylor [ i_z * tpv + (q-1)*r+1+ell ] is the q-th order Taylor coefficient corresponding to z in the ell-th direction. */ template inline void forward_cond_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , Base* taylor ) { Base y_0, y_1, y_2, y_3; Base zero(0); size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* z = taylor + i_z * num_taylor_per_var; CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast (CompareNe) ); CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); if( arg[1] & 1 ) { y_0 = taylor[ arg[2] * num_taylor_per_var + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); y_0 = parameter[ arg[2] ]; } if( arg[1] & 2 ) { y_1 = taylor[ arg[3] * num_taylor_per_var + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); y_1 = parameter[ arg[3] ]; } size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { if( arg[1] & 4 ) { y_2 = taylor[ arg[4] * num_taylor_per_var + m + ell]; } else y_2 = zero; if( arg[1] & 8 ) { y_3 = taylor[ arg[5] * num_taylor_per_var + m + ell]; } else y_3 = zero; z[m+ell] = CondExpOp( CompareOp( arg[0] ), y_0, y_1, y_2, y_3 ); } return; } /*! Compute zero order forward mode Taylor coefficients for op = CExpOp. The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \param parameter For j = 0, 1, 2, 3, if y_j is a parameter, \a parameter [ arg[2 + j] ] is its value. \param cap_order number of columns in the matrix containing the Taylor coefficients. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. \param taylor \b Input: For j = 0, 1, 2, 3, if y_j is a variable then \a taylor [ \a arg[2+j] * cap_order + 0 ] is the zero order Taylor coefficient corresponding to y_j. \n \b Output: \a taylor [ \a i_z * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to z. */ template inline void forward_cond_op_0( size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , Base* taylor ) { Base y_0, y_1, y_2, y_3; Base* z; CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast (CompareNe) ); CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); if( arg[1] & 1 ) { y_0 = taylor[ arg[2] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); y_0 = parameter[ arg[2] ]; } if( arg[1] & 2 ) { y_1 = taylor[ arg[3] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); y_1 = parameter[ arg[3] ]; } if( arg[1] & 4 ) { y_2 = taylor[ arg[4] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par ); y_2 = parameter[ arg[4] ]; } if( arg[1] & 8 ) { y_3 = taylor[ arg[5] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par ); y_3 = parameter[ arg[5] ]; } z = taylor + i_z * cap_order; z[0] = CondExpOp( CompareOp( arg[0] ), y_0, y_1, y_2, y_3 ); return; } /*! Compute reverse mode Taylor coefficients for op = CExpOp. This routine is given the partial derivatives of a function G( z , y , x , w , ... ) and it uses them to compute the partial derivatives of \verbatim H( y , x , w , u , ... ) = G[ z(y) , y , x , w , u , ... ] \endverbatim where y above represents y_0, y_1, y_2, y_3. The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \param parameter For j = 0, 1, 2, 3, if y_j is a parameter, \a parameter [ arg[2 + j] ] is its value. \param cap_order number of columns in the matrix containing the Taylor coefficients. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. \param d is the order of the Taylor coefficient of z that we are computing. \param taylor \b Input: For j = 0, 1, 2, 3 and k = 0 , ... , \a d, if y_j is a variable then \a taylor [ \a arg[2+j] * cap_order + k ] is the k-th order Taylor coefficient corresponding to y_j. \n \a taylor [ \a i_z * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to z. \param nc_partial number of columns in the matrix containing the Taylor coefficients. \param partial \b Input: For j = 0, 1, 2, 3 and k = 0 , ... , \a d, if y_j is a variable then \a partial [ \a arg[2+j] * nc_partial + k ] is the partial derivative of G( z , y , x , w , u , ... ) with respect to the k-th order Taylor coefficient corresponding to y_j. \n \b Input: \a partial [ \a i_z * \a cap_order + k ] for k = 0 , ... , \a d is the partial derivative of G( z , y , x , w , u , ... ) with respect to the k-th order Taylor coefficient corresponding to z. \n \b Output: For j = 0, 1, 2, 3 and k = 0 , ... , \a d, if y_j is a variable then \a partial [ \a arg[2+j] * nc_partial + k ] is the partial derivative of H( y , x , w , u , ... ) with respect to the k-th order Taylor coefficient corresponding to y_j. */ template inline void reverse_cond_op( size_t d , size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { Base y_0, y_1; Base zero(0); Base* pz; Base* py_2; Base* py_3; CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast (CompareNe) ); CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); pz = partial + i_z * nc_partial + 0; if( arg[1] & 1 ) { y_0 = taylor[ arg[2] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); y_0 = parameter[ arg[2] ]; } if( arg[1] & 2 ) { y_1 = taylor[ arg[3] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); y_1 = parameter[ arg[3] ]; } if( arg[1] & 4 ) { py_2 = partial + arg[4] * nc_partial; size_t j = d + 1; while(j--) { py_2[j] += CondExpOp( CompareOp( arg[0] ), y_0, y_1, pz[j], zero ); } } if( arg[1] & 8 ) { py_3 = partial + arg[5] * nc_partial; size_t j = d + 1; while(j--) { py_3[j] += CondExpOp( CompareOp( arg[0] ), y_0, y_1, zero, pz[j] ); } } return; } /*! Compute forward Jacobian sparsity patterns for op = CExpOp. The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. \param sparsity \b Input: if y_2 is a variable, the set with index t is the sparsity pattern corresponding to y_2. This identifies which of the independent variables the variable y_2 depends on. \n \b Input: if y_3 is a variable, the set with index t is the sparsity pattern corresponding to y_3. This identifies which of the independent variables the variable y_3 depends on. \n \b Output: The set with index T is the sparsity pattern corresponding to z. This identifies which of the independent variables the variable z depends on. */ template inline void forward_sparse_jacobian_cond_op( size_t i_z , const addr_t* arg , size_t num_par , Vector_set& sparsity ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast (CompareNe) ); CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); # ifndef NDEBUG if( arg[1] & 1 ) { } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); } if( arg[1] & 2 ) { } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); } # endif if( arg[1] & 4 ) { if( arg[1] & 8 ) { sparsity.binary_union(i_z, arg[4], arg[5], sparsity); } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par ); sparsity.assignment(i_z, arg[4], sparsity); } } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par ); if( arg[1] & 8 ) { sparsity.assignment(i_z, arg[5], sparsity); } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par ); sparsity.clear(i_z); } } return; } /*! Compute reverse Jacobian sparsity patterns for op = CExpOp. This routine is given the sparsity patterns for a function G(z, y, x, ... ) and it uses them to compute the sparsity patterns for \verbatim H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ] \endverbatim where y represents the combination of y_0, y_1, y_2, and y_3. The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. \param nz_compare Are the derivatives with respect to left and right of the expression below considered to be non-zero: \code CondExpRel(left, right, if_true, if_false) \endcode This is used by the optimizer to obtain the correct dependency relations. \param sparsity if y_2 is a variable, the set with index t is the sparsity pattern corresponding to y_2. This identifies which of the dependent variables depend on the variable y_2. On input, this pattern corresponds to the function G. On ouput, it corresponds to the function H. \n \n if y_3 is a variable, the set with index t is the sparsity pattern corresponding to y_3. This identifies which of the dependent variables depeond on the variable y_3. On input, this pattern corresponds to the function G. On ouput, it corresponds to the function H. \n \b Output: The set with index T is the sparsity pattern corresponding to z. This identifies which of the dependent variables depend on the variable z. On input and output, this pattern corresponds to the function G. */ template inline void reverse_sparse_jacobian_cond_op( bool nz_compare , size_t i_z , const addr_t* arg , size_t num_par , Vector_set& sparsity ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast (CompareNe) ); CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); # ifndef NDEBUG if( arg[1] & 1 ) { } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); } if( arg[1] & 2 ) { } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); } if( ! ( arg[1] & 4 ) ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par ); } if( ! ( arg[1] & 8 ) ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par ); } # endif if( nz_compare ) { if( arg[1] & 1 ) { sparsity.binary_union(arg[2], arg[2], i_z, sparsity); } if( arg[1] & 2 ) { sparsity.binary_union(arg[3], arg[3], i_z, sparsity); } } // -------------------------------------------------------------------- if( arg[1] & 4 ) { sparsity.binary_union(arg[4], arg[4], i_z, sparsity); } if( arg[1] & 8 ) { sparsity.binary_union(arg[5], arg[5], i_z, sparsity); } return; } /*! Compute reverse Hessian sparsity patterns for op = CExpOp. This routine is given the sparsity patterns for a function G(z, y, x, ... ) and it uses them to compute the sparsity patterns for \verbatim H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ] \endverbatim where y represents the combination of y_0, y_1, y_2, and y_3. The C++ source code coresponding to this operation is \verbatim z = CondExpRel(y_0, y_1, y_2, y_3) \endverbatim where Rel is one of the following: Lt, Le, Eq, Ge, Gt. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z is the AD variable index corresponding to the variable z. \param arg \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, y_0 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, y_1 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 4 \n If this is zero, y_2 is a parameter. Otherwise it is a variable. \n \n \a arg[1] & 8 \n If this is zero, y_3 is a parameter. Otherwise it is a variable. \n \n \a arg[2 + j ] for j = 0, 1, 2, 3 \n is the index corresponding to y_j. \param num_par is the total number of values in the vector \a parameter. \par Checked Assertions \li NumArg(CExpOp) == 6 \li NumRes(CExpOp) == 1 \li arg[0] < static_cast ( CompareNe ) \li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters. \li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par. \param jac_reverse \a jac_reverse[i_z] is false (true) if the Jacobian of G with respect to z is always zero (may be non-zero). \n \n \a jac_reverse[ arg[4] ] If y_2 is a variable, \a jac_reverse[ arg[4] ] is false (true) if the Jacobian with respect to y_2 is always zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. \n \n \a jac_reverse[ arg[5] ] If y_3 is a variable, \a jac_reverse[ arg[5] ] is false (true) if the Jacobian with respect to y_3 is always zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. \param hes_sparsity The set with index \a i_z in \a hes_sparsity is the Hessian sparsity pattern for the function G where one of the partials is with respect to z. \n \n If y_2 is a variable, the set with index \a arg[4] in \a hes_sparsity is the Hessian sparsity pattern where one of the partials is with respect to y_2. On input, this pattern corresponds to the function G. On output, this pattern corresponds to the function H. \n \n If y_3 is a variable, the set with index \a arg[5] in \a hes_sparsity is the Hessian sparsity pattern where one of the partials is with respect to y_3. On input, this pattern corresponds to the function G. On output, this pattern corresponds to the function H. */ template inline void reverse_sparse_hessian_cond_op( size_t i_z , const addr_t* arg , size_t num_par , bool* jac_reverse , Vector_set& hes_sparsity ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast (CompareNe) ); CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); # ifndef NDEBUG if( arg[1] & 1 ) { } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); } if( arg[1] & 2 ) { } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); } if( ! ( arg[1] & 4 ) ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par ); } if( ! ( arg[1] & 8 ) ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par ); } # endif if( arg[1] & 4 ) { hes_sparsity.binary_union(arg[4], arg[4], i_z, hes_sparsity); jac_reverse[ arg[4] ] |= jac_reverse[i_z]; } if( arg[1] & 8 ) { hes_sparsity.binary_union(arg[5], arg[5], i_z, hes_sparsity); jac_reverse[ arg[5] ] |= jac_reverse[i_z]; } return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/abs.hpp0000644000176200001440000001075614536067013016751 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ABS_INCLUDED # define CPPAD_ABS_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin abs$$ $spell fabs Vec std faq Taylor Cpp namespace const abs $$ $index abs, AD$$ $index fabs, AD$$ $index absolute, AD value$$ $index value, AD absolute$$ $section AD Absolute Value Function$$ $head Syntax$$ $icode%y% = abs(%x%) %$$ $icode%y% = fabs(%x%)%$$ $head Purpose$$ Evaluates the absolute value function. $head x$$ The argument $icode x$$ has one of the following prototypes $codei% const AD<%Base%> &%x% const VecAD<%Base%>::reference &%x% %$$ $head y$$ The result $icode y$$ has prototype $codei% AD<%Base%> %y% %$$ $head Operation Sequence$$ This is an AD of $icode Base$$ $cref/atomic operation/glossary/Operation/Atomic/$$ and hence is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Complex Types$$ The function $code abs$$ is not defined for the AD type sequences above $code std::complex$$ or $code std::complex$$ because the complex $code abs$$ function is not complex differentiable (see $cref/complex types faq/Faq/Complex Types/$$). $head Derivative$$ CppAD defines the derivative of the $code abs$$ function is the $cref sign$$ function; i.e., $latex \[ {\rm abs}^{(1)} ( x ) = {\rm sign} (x ) = \left\{ \begin{array}{rl} +1 & {\rm if} \; x > 0 \\ 0 & {\rm if} \; x = 0 \\ -1 & {\rm if} \; x < 0 \end{array} \right. \] $$ This used to be different; see $cref/old derivative/abs/Old Derivative/$$ below. $head Example$$ $children% example/abs.cpp %$$ The file $cref abs.cpp$$ contains an example and test of this function. It returns true if it succeeds and false otherwise. $head Old Derivative$$ The derivative of the absolute value function is one for $latex x > 0$$ and minus one for $latex x < 0$$. CppAD used to compute its directional derivative what $latex x = 0$$. $pre $$ The function corresponding to the argument $icode x$$ and the result $icode y$$ are represented by their Taylor coefficients; i.e., $latex \[ \begin{array}{rcl} X(t) & = & x^{(0)} (t) + x^{(1)} t + \cdots + x^{(p)} t^p \\ Y(t) & = & y^{(0)} (t) + y^{(1)} t + \cdots + y^{(p)} t^p \end{array} \] $$ Note that $latex x^{(0)} = X(0)$$ is the value of $icode x$$ and $latex y^{(0)} = Y(0)$$ is the value of $icode y$$. In the equations above, the order $latex p$$ is specified by a call to $cref Forward$$ or $cref Reverse$$ as follows: $codei% %f%.Forward(%p%, %dx%) %f%.Reverse(%p%+1, %w%) %$$ If all of the Taylor coefficients of $latex X(t)$$ are zero, we define $latex k = p$$. Otherwise, we define $latex k$$ to be the minimal index such that $latex x^{(k)} \neq 0$$. Note that if $latex x \neq 0$$, $latex k = 0$$. The Taylor coefficient representation of $latex Y(t)$$ (and hence it's derivatives) are computed as $latex \[ y^{(\ell)} = \left\{ \begin{array}{ll} x^{(\ell)} & {\rm if} \; x^{(k)} > 0 \\ 0 & {\rm if} \; x^{(k)} = 0 \\ - x^{(\ell)} & {\rm if} \; x^{(k)} < 0 \end{array} \right. \] $$ $end ------------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD AD::Abs (void) const { AD result; result.value_ = abs(value_); CPPAD_ASSERT_UNKNOWN( Parameter(result) ); if( Variable(*this) ) { // add this operation to the tape CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 ); ADTape *tape = tape_this(); // corresponding operand address tape->Rec_.PutArg(taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(AbsOp); // make result a variable result.tape_id_ = tape->id_; } return result; } template inline AD abs(const AD &x) { return x.Abs(); } template inline AD abs(const VecAD_reference &x) { return abs( x.ADBase() ); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/base_float.hpp0000644000176200001440000001225514536067013020277 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BASE_FLOAT_INCLUDED # define CPPAD_BASE_FLOAT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include /* $begin base_float.hpp$$ $spell erf endif abs_geq acos asin atan cos sqrt tanh std fabs bool Lt Le Eq Ge Gt Rel CppAD CondExpOp namespace inline enum const exp const $$ $index float, Base$$ $index Base, float$$ $index float, Base$$ $section Enable use of AD where Base is float$$ $head CondExpOp$$ The type $code float$$ is a relatively simple type that supports $code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators; see $cref/ordered type/base_cond_exp/CondExpTemplate/Ordered Type/$$. Hence its $code CondExpOp$$ function is defined by $codep */ namespace CppAD { inline float CondExpOp( enum CompareOp cop , const float& left , const float& right , const float& exp_if_true , const float& exp_if_false ) { return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false); } } /* $$ $head CondExpRel$$ The $cref/CPPAD_COND_EXP_REL/base_cond_exp/CondExpRel/$$ macro invocation $codep */ namespace CppAD { CPPAD_COND_EXP_REL(float) } /* $$ uses $code CondExpOp$$ above to define $codei%CondExp%Rel%$$ for $code float$$ arguments and $icode%Rel%$$ equal to $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, and $code Gt$$. $head EqualOpSeq$$ The type $code float$$ is simple (in this respect) and so we define $codep */ namespace CppAD { inline bool EqualOpSeq(const float& x, const float& y) { return x == y; } } /* $$ $head Identical$$ The type $code float$$ is simple (in this respect) and so we define $codep */ namespace CppAD { inline bool IdenticalPar(const float& x) { return true; } inline bool IdenticalZero(const float& x) { return (x == 0.f); } inline bool IdenticalOne(const float& x) { return (x == 1.f); } inline bool IdenticalEqualPar(const float& x, const float& y) { return (x == y); } } /* $$ $head Integer$$ $codep */ namespace CppAD { inline int Integer(const float& x) { return static_cast(x); } } /* $$ $head Ordered$$ The $code float$$ type supports ordered comparisons $codep */ namespace CppAD { inline bool GreaterThanZero(const float& x) { return x > 0.f; } inline bool GreaterThanOrZero(const float& x) { return x >= 0.f; } inline bool LessThanZero(const float& x) { return x < 0.f; } inline bool LessThanOrZero(const float& x) { return x <= 0.f; } inline bool abs_geq(const float& x, const float& y) { return std::fabs(x) >= std::fabs(y); } } /* $$ $head Unary Standard Math$$ The following macro invocations define the unary standard math functions required to use $code AD$$: (in the CppAD namespace) $codep */ namespace CppAD { CPPAD_STANDARD_MATH_UNARY(float, acos) CPPAD_STANDARD_MATH_UNARY(float, asin) CPPAD_STANDARD_MATH_UNARY(float, atan) CPPAD_STANDARD_MATH_UNARY(float, cos) CPPAD_STANDARD_MATH_UNARY(float, cosh) CPPAD_STANDARD_MATH_UNARY(float, exp) CPPAD_STANDARD_MATH_UNARY(float, fabs) CPPAD_STANDARD_MATH_UNARY(float, log) CPPAD_STANDARD_MATH_UNARY(float, log10) CPPAD_STANDARD_MATH_UNARY(float, sin) CPPAD_STANDARD_MATH_UNARY(float, sinh) CPPAD_STANDARD_MATH_UNARY(float, sqrt) CPPAD_STANDARD_MATH_UNARY(float, tan) CPPAD_STANDARD_MATH_UNARY(float, tanh) # if CPPAD_COMPILER_HAS_ERF CPPAD_STANDARD_MATH_UNARY(float, erf) # endif } /* $$ The absolute value function is special because its $code std$$ name is $code fabs$$ $codep */ namespace CppAD { inline float abs(const float& x) { return std::fabs(x); } } /* $$ $head sign$$ The following defines the $code CppAD::sign$$ function that is required to use $code AD$$: $codep */ namespace CppAD { inline float sign(const float& x) { if( x > 0.f ) return 1.f; if( x == 0.f ) return 0.f; return -1.f; } } /* $$ $head pow $$ The following defines a $code CppAD::pow$$ function that is required to use $code AD$$: $codep */ namespace CppAD { inline float pow(const float& x, const float& y) { return std::pow(x, y); } } /*$$ $head limits$$ The following defines the numeric limits functions $code epsilon$$, $code min$$, and $code max$$ for the type $code float$$: $codep */ namespace CppAD { template <> class numeric_limits { public: // machine epsilon static float epsilon(void) { return std::numeric_limits::epsilon(); } // minimum positive normalized value static float min(void) { return std::numeric_limits::min(); } // maximum finite value static float max(void) { return std::numeric_limits::max(); } }; // deprecated machine epsilon template <> inline float epsilon(void) { return numeric_limits::epsilon(); } } /* $$ $end */ # endif TMB/inst/include/cppad/local/tan_op.hpp0000644000176200001440000001362714536067013017464 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_TAN_OP_INCLUDED # define CPPAD_TAN_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file tan_op.hpp Forward and reverse mode calculations for z = tan(x). */ /*! Compute forward mode Taylor coefficient for result of op = TanOp. The C++ source code corresponding to this operation is \verbatim z = tan(x) \endverbatim The auxillary result is \verbatim y = tan(x)^2 \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_tan_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; Base* y = z - cap_order; size_t k; if( p == 0 ) { z[0] = tan( x[0] ); y[0] = z[0] * z[0]; p++; } for(size_t j = p; j <= q; j++) { Base base_j = static_cast(j); z[j] = x[j]; for(k = 1; k <= j; k++) z[j] += Base(k) * x[k] * y[j-k] / base_j; y[j] = z[0] * z[j]; for(k = 1; k <= j; k++) y[j] += z[k] * z[j-k]; } } /*! Multiple directions forward mode Taylor coefficient for op = TanOp. The C++ source code corresponding to this operation is \verbatim z = tan(x) \endverbatim The auxillary result is \verbatim y = tan(x)^2 \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_tan_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; Base* y = z - num_taylor_per_var; size_t k; size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { z[m+ell] = Base(q) * ( x[m+ell] + x[m+ell] * y[0]); for(k = 1; k < q; k++) z[m+ell] += Base(k) * x[(k-1)*r+1+ell] * y[(q-k-1)*r+1+ell]; z[m+ell] /= Base(q); // y[m+ell] = Base(2) * z[m+ell] * z[0]; for(k = 1; k < q; k++) y[m+ell] += z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell]; } } /*! Compute zero order forward mode Taylor coefficient for result of op = TanOp. The C++ source code corresponding to this operation is \verbatim z = tan(x) \endverbatim The auxillary result is \verbatim y = cos(x) \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_tan_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; // called z in documentation Base* y = z - cap_order; // called y in documentation z[0] = tan( x[0] ); y[0] = z[0] * z[0]; } /*! Compute reverse mode partial derivatives for result of op = TanOp. The C++ source code corresponding to this operation is \verbatim z = tan(x) \endverbatim The auxillary result is \verbatim y = cos(x) \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_tan_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* z = taylor + i_z * cap_order; // called z in doc Base* pz = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* y = z - cap_order; // called y in documentation Base* py = pz - nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; size_t j = d; size_t k; Base base_two(2); while(j) { px[j] += pz[j]; pz[j] /= Base(j); for(k = 1; k <= j; k++) { px[k] += pz[j] * y[j-k] * Base(k); py[j-k] += pz[j] * x[k] * Base(k); } for(k = 0; k < j; k++) pz[k] += py[j-1] * z[j-k-1] * base_two; --j; } px[0] += pz[0] * (Base(1) + y[0]); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/tape_link.hpp0000644000176200001440000002354314536067013020150 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_TAPE_LINK_INCLUDED # define CPPAD_TAPE_LINK_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file tape_link.hpp Routines that Link AD and ADTape Objects. The routines that connect the AD class to the corresponding tapes (one for each thread). */ /*! Handle to the tape identifier for this AD class and the specific thread. \tparam Base is the base type for this AD class. \param thread is the thread number. The following condition must hold \code (! thread_alloc::in_parallel()) || thread == thread_alloc::thread_num() \endcode \return is a handle to the tape identifier for this thread and AD class. */ template inline tape_id_t** AD::tape_id_handle(size_t thread) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static tape_id_t* tape_id_table[CPPAD_MAX_NUM_THREADS]; CPPAD_ASSERT_UNKNOWN( (! thread_alloc::in_parallel()) || thread == thread_alloc::thread_num() ); return tape_id_table + thread; } /*! Pointer to the tape identifier for this AD class and the specific thread. \tparam Base is the base type for this AD class. \param thread is the thread number; i.e., \code thread == thread_alloc::thread_num() \endcode If this condition is not satisfied, and \c NDEBUG is not defined, a CPPAD_ASSERT_UNKNOWN is generated. \return is a pointer to the tape identifier for this thread and AD class. \par Restrictions This routine should only be called if there was a tape created for the specified thread (it may no longer be recording). */ template inline tape_id_t* AD::tape_id_ptr(size_t thread) { CPPAD_ASSERT_UNKNOWN( *tape_id_handle(thread) != CPPAD_NULL ) return *tape_id_handle(thread); } /*! Handle for the tape for this AD class and the specific thread. \tparam Base is the base type for this AD class. \param thread is the thread number; i.e., \code thread == thread_alloc::thread_num() \endcode If this condition is not satisfied, and \c NDEBUG is not defined, a CPPAD_ASSERT_UNKNOWN is generated. \return is a handle for the AD class and the specified thread. */ template inline ADTape** AD::tape_handle(size_t thread) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static ADTape* tape_table[CPPAD_MAX_NUM_THREADS]; CPPAD_ASSERT_UNKNOWN( thread == thread_alloc::thread_num() ); return tape_table + thread; } /*! Pointer for the tape for this AD class and the current thread. \code thread == thread_alloc::thread_num() \endcode \tparam Base is the base type corresponding to AD operations. \return is a pointer to the tape that is currently recording AD operations for the current thread. If this value is \c CPPAD_NULL, there is no tape currently recording AD operations for this thread. */ template inline ADTape* AD::tape_ptr(void) { size_t thread = thread_alloc::thread_num(); return *tape_handle(thread); } /*! Pointer for the tape for this AD class and the specified tape identifier. \tparam Base is the base type corresponding to AD operations. \param tape_id is the identifier for the tape that is currently recording AD operations for the current thread. It must hold that the current thread is \code thread = size_t( tape_id % CPPAD_MAX_NUM_THREADS ) \endcode and that there is a tape recording AD operations for this thread. If this is not the currently executing thread, a variable from a different thread is being recorded on the tape for this thread which is a user error. \return is a pointer to the tape that is currently recording AD operations for the current thread (and it is not \c CPPAD_NULL). \par Restrictions This routine should only be called if there is a tape recording operaitons for the specified thread. */ template inline ADTape* AD::tape_ptr(tape_id_t tape_id) { size_t thread = size_t( tape_id % CPPAD_MAX_NUM_THREADS ); CPPAD_ASSERT_KNOWN( thread == thread_alloc::thread_num(), "Attempt to use an AD variable with two different threads." ); CPPAD_ASSERT_UNKNOWN( tape_id == *tape_id_ptr(thread) ); CPPAD_ASSERT_UNKNOWN( *tape_handle(thread) != CPPAD_NULL ); return *tape_handle(thread); } /*! Create and delete tapes that record AD operations for current thread. \par thread the current thread is given by \code thread = thread_alloc::thread_num() \endcode \tparam Base is the base type corresponding to AD operations. \param job This argument determines if we are creating a new tape, or deleting an old one. - \c tape_manage_new : Creates and a new tape. It is assumed that there is no tape recording AD operations for this thread when \c tape_manage is called. It the input value of *tape_id_handle(thread) is \c CPPAD_NULL, it will be changed to a non-zero pointer and the corresponding value of *tape_id_ptr(thread) will be set to thread + CPPAD_MAX_NUM_THREADS. - \c tape_manage_delete : It is assumed that there is a tape recording AD operations for this thread when \c tape_manage is called. The value of *tape_id_ptr(thread) will be advanced by \c CPPAD_MAX_NUM_THREADS. \return - job == tape_manage_new: a pointer to the new tape is returned. - job == tape_manage_delete: the value \c CPPAD_NULL is returned. */ template ADTape* AD::tape_manage(tape_manage_job job) { // this routine has static variables so first call cannot be in parallel CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL // The tape for the master thread static ADTape tape_zero; // Pointer to the tape for each thread static ADTape* tape_table[CPPAD_MAX_NUM_THREADS]; // The id current being used for each of the tapes static tape_id_t tape_id_save[CPPAD_MAX_NUM_THREADS]; // Thread corresponding to this call size_t thread = thread_alloc::thread_num(); // tape_manage_clear if( job == tape_manage_clear ) { // This operation cannot be done in parallel CPPAD_ASSERT_UNKNOWN(thread == 0 && (! thread_alloc::in_parallel())); for(thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++) { // if this thread has a tape if( tape_table[thread] != CPPAD_NULL ) { // id corresponding to this thread tape_id_save[thread] = tape_table[thread]->id_; *tape_id_handle(thread) = &tape_id_save[thread]; // delete all but the master thread if( thread != 0 ) delete( tape_table[thread] ); // set the tape pointer to null tape_table[thread] = CPPAD_NULL; } } return CPPAD_NULL; } // id and tape fpor this thread tape_id_t** tape_id = tape_id_handle(thread); ADTape** tape = tape_handle(thread); // check if there is no tape currently attached to this thread if( tape_table[thread] == CPPAD_NULL ) { // allocate separate memroy to avoid false sharing if( thread == 0 ) { // mastert tape is a static in this routine tape_table[thread] = &tape_zero; } else { // other tapes are allocated tape_table[thread] = new ADTape(); } // current id and pointer to this tape tape_table[thread]->id_ = tape_id_save[thread]; *tape_id = &tape_table[thread]->id_; // if id is zero, initialize it so that // thread == tape id % CPPAD_MAX_NUM_THREADS if( **tape_id == 0 ) **tape_id = thread + CPPAD_MAX_NUM_THREADS; } // make sure tape_id_handle(thread) is pointing to the proper place CPPAD_ASSERT_UNKNOWN( *tape_id == &tape_table[thread]->id_ ); // make sure tape_id value is valid for this thread CPPAD_ASSERT_UNKNOWN( size_t( **tape_id % CPPAD_MAX_NUM_THREADS ) == thread ); switch(job) { case tape_manage_new: // tape for this thread must be null at the start CPPAD_ASSERT_UNKNOWN( *tape == CPPAD_NULL ); *tape = tape_table[thread]; break; case tape_manage_delete: CPPAD_ASSERT_UNKNOWN( *tape == tape_table[thread] ); CPPAD_ASSERT_KNOWN( std::numeric_limits::max() - CPPAD_MAX_NUM_THREADS > **tape_id, "To many different tapes given the type used for " "CPPAD_TAPE_ID_TYPE" ); // advance tape identfier so all AD variables become parameters **tape_id += CPPAD_MAX_NUM_THREADS; // free memory corresponding to recording in the old tape tape_table[thread]->Rec_.free(); // inform rest of CppAD that no tape recording for this thread *tape = CPPAD_NULL; break; case tape_manage_clear: CPPAD_ASSERT_UNKNOWN(false); } return *tape; } /*! Get a pointer to tape that records AD operations for the current thread. \tparam Base is the base type corresponding to AD operations. \par thread The current thread must be given by \code thread = this->tape_id_ % CPPAD_MAX_NUM_THREADS \endcode \return is a pointer to the tape that is currently recording AD operations for the current thread. This value must not be \c CPPAD_NULL; i.e., there must be a tape currently recording AD operations for this thread. */ template inline ADTape *AD::tape_this(void) const { size_t thread = size_t( tape_id_ % CPPAD_MAX_NUM_THREADS ); CPPAD_ASSERT_UNKNOWN( tape_id_ == *tape_id_ptr(thread) ); CPPAD_ASSERT_UNKNOWN( *tape_handle(thread) != CPPAD_NULL ); return *tape_handle(thread); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/erf_op.hpp0000644000176200001440000002667014536067013017460 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ERF_OP_INCLUDED # define CPPAD_ERF_OP_INCLUDED # if CPPAD_COMPILER_HAS_ERF /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file erf_op.hpp Forward and reverse mode calculations for z = erf(x). */ /*! Forward mode Taylor coefficient for result of op = ErfOp. The C++ source code corresponding to this operation is \verbatim z = erf(x) \endverbatim \par CPPAD_HAS_ERROF_FUNCTION This macro is either zero or one and forward_erf_op is only defined when it is one. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param p lowest order of the Taylor coefficients that we are computing. \param q highest order of the Taylor coefficients that we are computing. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. The auxillary result is called y has index \a i_z - 1. \param arg arg[0]: is the variable index corresponding to x. \n arg[1]: is the parameter index corresponding to the value zero. \n \arg[2]: is the parameter index correspodning to the value 2 / sqrt(pi). \param parameter parameter[ arg[1] ] is the value zero, and parameter[ arg[2] ] is the value 2 / sqrt(pi). \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: taylor [ arg[0] * cap_order + k ] for k = 0 , ... , q, is the k-th order Taylor coefficient corresponding to x. \n \b Input: taylor [ i_z * cap_order + k ] for k = 0 , ... , p - 1, is the k-th order Taylor coefficient corresponding to z. \n \b Input: taylor [ ( i_z - j) * cap_order + k ] for k = 0 , ... , p-1, and j = 0 , ... , 4, is the k-th order Taylor coefficient corresponding to the j-th result for z. \n \b Output: taylor [ (i_z-j) * cap_order + k ], for k = p , ... , q, and j = 0 , ... , 4, is the k-th order Taylor coefficient corresponding to the j-th result for z. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 5 \li q < cap_order \li p <= q */ template inline void forward_erf_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // array used to pass parameter values for sub-operations addr_t addr[2]; // convert from final result to first result i_z -= 4; // 4 = NumRes(ErfOp) - 1; // z_0 = x * x addr[0] = arg[0]; // x addr[1] = arg[0]; // x forward_mulvv_op(p, q, i_z+0, addr, parameter, cap_order, taylor); // z_1 = - x * x addr[0] = arg[1]; // zero addr[1] = i_z; // z_0 forward_subpv_op(p, q, i_z+1, addr, parameter, cap_order, taylor); // z_2 = exp( - x * x ) forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor); // z_3 = (2 / sqrt(pi)) * exp( - x * x ) addr[0] = arg[2]; // 2 / sqrt(pi) addr[1] = i_z + 2; // z_2 forward_mulpv_op(p, q, i_z+3, addr, parameter, cap_order, taylor); // pointers to taylor coefficients for x , z_3, and z_4 Base* x = taylor + arg[0] * cap_order; Base* z_3 = taylor + (i_z+3) * cap_order; Base* z_4 = taylor + (i_z+4) * cap_order; // calculte z_4 coefficients if( p == 0 ) { // zero order Taylor coefficient for z_4 z_4[0] = erf(x[0]); p++; } for(size_t j = p; j <= q; j++) { Base base_j = static_cast(j); z_4[j] = static_cast(0); for(size_t k = 1; k <= j; k++) z_4[j] += (Base(k) / base_j) * x[k] * z_3[j-k]; } } /*! Zero order Forward mode Taylor coefficient for result of op = ErfOp. The C++ source code corresponding to this operation is \verbatim z = erf(x) \endverbatim \par CPPAD_HAS_ERROF_FUNCTION This macro is either zero or one and forward_erf_op is only defined when it is one. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. The auxillary result is called y has index \a i_z - 1. \param arg arg[0]: is the variable index corresponding to x. \n arg[1]: is the parameter index corresponding to the value zero. \n \arg[2]: is the parameter index correspodning to the value 2 / sqrt(pi). \param parameter parameter[ arg[1] ] is the value zero, and parameter[ arg[2] ] is the value 2 / sqrt(pi). \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: taylor [ arg[0] * cap_order + 0 ] is the zero order Taylor coefficient corresponding to x. \n \b Input: taylor [ i_z * cap_order + 0 ] is the zero order Taylor coefficient corresponding to z. \n \b Output: taylor [ (i_z-j) * cap_order + 0 ], for j = 0 , ... , 4, is the zero order Taylor coefficient for j-th result corresponding to z. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 5 \li q < cap_order \li p <= q */ template inline void forward_erf_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // array used to pass parameter values for sub-operations addr_t addr[2]; // convert from final result to first result i_z -= 4; // 4 = NumRes(ErfOp) - 1; // z_0 = x * x addr[0] = arg[0]; // x addr[1] = arg[0]; // x forward_mulvv_op_0(i_z+0, addr, parameter, cap_order, taylor); // z_1 = - x * x addr[0] = arg[1]; // zero addr[1] = i_z; // z_0 forward_subpv_op_0(i_z+1, addr, parameter, cap_order, taylor); // z_2 = exp( - x * x ) forward_exp_op_0(i_z+2, i_z+1, cap_order, taylor); // z_3 = (2 / sqrt(pi)) * exp( - x * x ) addr[0] = arg[2]; // 2 / sqrt(pi) addr[1] = i_z + 2; // z_2 forward_mulpv_op_0(i_z+3, addr, parameter, cap_order, taylor); // zero order Taylor coefficient for z_4 Base* x = taylor + arg[0] * cap_order; Base* z_4 = taylor + (i_z + 4) * cap_order; z_4[0] = erf(x[0]); } /*! Compute reverse mode partial derivatives for result of op = ErfOp. The C++ source code corresponding to this operation is \verbatim z = erf(x) \endverbatim \par CPPAD_HAS_ERROF_FUNCTION This macro is either zero or one and reverse_tan_op is only defined when it is one. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param d highest order Taylor of the Taylor coefficients that we are computing the partial derivatives with respect to. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. The auxillary result is called y has index \a i_z - 1. \param arg arg[0]: is the variable index corresponding to x. \n arg[1]: is the parameter index corresponding to the value zero. \n \arg[2]: is the parameter index correspodning to the value 2 / sqrt(pi). \param parameter parameter[ arg[1] ] is the value zero, and parameter[ arg[2] ] is the value 2 / sqrt(pi). \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: taylor [ arg[0] * cap_order + k ] for k = 0 , ... , d, is the k-th order Taylor coefficient corresponding to x. \n taylor [ (i_z - j) * cap_order + k ] for k = 0 , ... , d, and for j = 0 , ... , 4, is the k-th order Taylor coefficient corresponding to the j-th result for this operation. \param nc_partial number of columns in the matrix containing all the partial derivatives \param partial \b Input: partial [ arg[0] * nc_partial + k ] for k = 0 , ... , d, is the partial derivative of G( z , x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Input: partial [ (i_z - j) * nc_partial + k ] for k = 0 , ... , d, and for j = 0 , ... , 4, is the partial derivative of G( z , x , w , u , ... ) with respect to the k-th order Taylor coefficient for the j-th result of this operation. \n \b Output: partial [ arg[0] * nc_partial + k ] for k = 0 , ... , d, is the partial derivative of H( x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Output: partial [ (i_z-j) * nc_partial + k ] for k = 0 , ... , d, and for j = 0 , ... , 4, may be used as work space; i.e., may change in an unspecified manner. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 5 \li q < cap_order \li p <= q */ template inline void reverse_erf_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); // array used to pass parameter values for sub-operations addr_t addr[2]; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). Base* pz = partial + i_z * nc_partial; bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; // convert from final result to first result i_z -= 4; // 4 = NumRes(ErfOp) - 1; // Taylor coefficients and partials corresponding to x const Base* x = taylor + arg[0] * cap_order; Base* px = partial + arg[0] * nc_partial; // Taylor coefficients and partials corresponding to z_3 const Base* z_3 = taylor + (i_z+3) * cap_order; Base* pz_3 = partial + (i_z+3) * nc_partial; // Taylor coefficients and partials corresponding to z_4 Base* pz_4 = partial + (i_z+4) * nc_partial; // Reverse z_4 size_t j = d; while(j) { pz_4[j] /= Base(j); for(size_t k = 1; k <= j; k++) { px[k] += pz_4[j] * z_3[j-k] * Base(k); pz_3[j-k] += pz_4[j] * x[k] * Base(k); } j--; } px[0] += pz_4[0] * z_3[0]; // z_3 = (2 / sqrt(pi)) * exp( - x * x ) addr[0] = arg[2]; // 2 / sqrt(pi) addr[1] = i_z + 2; // z_2 reverse_mulpv_op( d, i_z+3, addr, parameter, cap_order, taylor, nc_partial, partial ); // z_2 = exp( - x * x ) reverse_exp_op( d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial ); // z_1 = - x * x addr[0] = arg[1]; // zero addr[1] = i_z; // z_0 reverse_subpv_op( d, i_z+1, addr, parameter, cap_order, taylor, nc_partial, partial ); // z_0 = x * x addr[0] = arg[0]; // x addr[1] = arg[0]; // x reverse_mulvv_op( d, i_z+0, addr, parameter, cap_order, taylor, nc_partial, partial ); } } // END_CPPAD_NAMESPACE # endif // CPPAD_COMPILER_HAS_ERF # endif // CPPAD_ERF_OP_INCLUDED TMB/inst/include/cppad/local/ad_io.hpp0000644000176200001440000001303514536067013017250 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_AD_IO_INCLUDED # define CPPAD_AD_IO_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ad_input$$ $spell VecAD std istream const $$ $index >>, AD input$$ $index AD, stream input$$ $index input, AD$$ $index stream, AD input$$ $index write, AD$$ $section AD Output Stream Operator$$ $head Syntax$$ $icode%is% >> %x%$$ $head Purpose$$ Sets $icode x$$ to a $cref/parameter/glossary/Parameter/$$ with value $icode b$$ corresponding to $codei% %is% >> %b% %$$ where $icode b$$ is a $icode Base$$ object. It is assumed that this $icode Base$$ input operation returns a reference to $icode is$$. $head is$$ The operand $icode is$$ has prototype $codei% std::istream& %is% %$$ $head x$$ The operand $icode x$$ has one of the following prototypes $codei% AD<%Base%>& %x% %$$ $head Result$$ The result of this operation can be used as a reference to $icode is$$. For example, if the operand $icode y$$ has prototype $codei% AD<%Base%> %y% %$$ then the syntax $codei% %is% >> %x% >> %y% %$$ will first read the $icode Base$$ value of $icode x$$ from $icode is$$, and then read the $icode Base$$ value to $icode y$$. $head Operation Sequence$$ The result of this operation is not an $cref/AD of Base/glossary/AD of Base/$$ object. Thus it will not be recorded as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Example$$ $children% example/ad_input.cpp %$$ The file $cref ad_input.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------ $begin ad_output$$ $spell VecAD std ostream const $$ $index <<, AD output$$ $index AD, stream output$$ $index output, AD$$ $index stream, AD output$$ $index write, AD$$ $section AD Output Stream Operator$$ $head Syntax$$ $icode%os% << %x%$$ $head Purpose$$ Writes the $icode Base$$ value, corresponding to $icode x$$, to the output stream $icode os$$. $head Assumption$$ If $icode b$$ is a $icode Base$$ object, $codei% %os% << %b% %$$ returns a reference to $icode os$$. $head os$$ The operand $icode os$$ has prototype $codei% std::ostream& %os% %$$ $head x$$ The operand $icode x$$ has one of the following prototypes $codei% const AD<%Base%>& %x% const VecAD<%Base%>::reference& %x% %$$ $head Result$$ The result of this operation can be used as a reference to $icode os$$. For example, if the operand $icode y$$ has prototype $codei% AD<%Base%> %y% %$$ then the syntax $codei% %os% << %x% << %y% %$$ will output the value corresponding to $icode x$$ followed by the value corresponding to $icode y$$. $head Operation Sequence$$ The result of this operation is not an $cref/AD of Base/glossary/AD of Base/$$ object. Thus it will not be recorded as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Example$$ $children% example/ad_output.cpp %$$ The file $cref ad_output.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------ */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file ad_io.hpp AD input and ouput stream operators. */ // --------------------------------------------------------------------------- /*! Read an AD object from an input stream. \tparam Base Base type for the AD object. \param is [in,out] Is the input stream from which that value is read. \param x [out] is the object that is being set to a value. Upone return, x.value_ is read from the input stream and x.tape_is_ is zero; i.e., x is a parameter. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION std::istream& operator >> (std::istream& is, AD& x) { // like assignment to a base type value x.tape_id_ = 0; CPPAD_ASSERT_UNKNOWN( Parameter(x) ); return (is >> x.value_); } // --------------------------------------------------------------------------- /*! Write an AD object to an output stream. \tparam Base Base type for the AD object. \param os [in,out] Is the output stream to which that value is written. \param x is the object that is being written to the output stream. This is equivalent to writing x.value_ to the output stream. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION std::ostream& operator << (std::ostream &os, const AD &x) { return (os << x.value_); } // --------------------------------------------------------------------------- /*! Write a VecAD_reference object to an output stream. \tparam Base Base type for the VecAD_reference object. \param os [in,out] Is the output stream to which that value is written. \param x is the element of the VecAD object that is being written to the output stream. This is equivalent to writing the corresponing Base value to the stream. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION std::ostream& operator << (std::ostream &os, const VecAD_reference &x) { return (os << x.ADBase()); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/forward1sweep.hpp0000644000176200001440000006420714536067013020775 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FORWARD1SWEEP_INCLUDED # define CPPAD_FORWARD1SWEEP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file forward1sweep.hpp Compute one Taylor coefficient for each order requested. */ /* \def CPPAD_ATOMIC_CALL This avoids warnings when NDEBUG is defined and user_ok is not used. If NDEBUG is defined, this resolves to \code user_atom->forward \endcode otherwise, it respolves to \code user_ok = user_atom->forward \endcode This macro is undefined at the end of this file to facillitate its use with a different definition in other files. */ # ifdef NDEBUG # define CPPAD_ATOMIC_CALL user_atom->forward # else # define CPPAD_ATOMIC_CALL user_ok = user_atom->forward # endif /*! \def CPPAD_FORWARD1SWEEP_TRACE This value is either zero or one. Zero is the normal operational value. If it is one, a trace of every forward1sweep computation is printed. */ # define CPPAD_FORWARD1SWEEP_TRACE 0 /*! Compute arbitrary order forward mode Taylor coefficients. \tparam Base The type used during the forward mode computations; i.e., the corresponding recording of operations used the type AD. \param s_out Is the stream where output corresponding to PriOp operations will be written. \param print If print is false, suppress the output that is otherwise generated by the c PriOp instructions. \param n is the number of independent variables on the tape. \param numvar is the total number of variables on the tape. This is also equal to the number of rows in the matrix taylor; i.e., play->num_var_rec(). \param play The information stored in play is a recording of the operations corresponding to the function \f[ F : {\bf R}^n \rightarrow {\bf R}^m \f] where \f$ n \f$ is the number of independent variables and \f$ m \f$ is the number of dependent variables. \n \n The object play is effectly constant. The exception to this is that while palying back the tape the object play holds information about the current location with in the tape and this changes during palyback. \param J Is the number of columns in the coefficient matrix taylor. This must be greater than or equal one. \param cskip_op Is a vector with size play->num_op_rec(). \n \n p = 0 \n In this case, the input value of the elements does not matter. Upon return, if cskip_op[i] is true, the operator with index i does not affect any of the dependent variable (given the value of the independent variables). \n \n p > 0 \n In this case cskip_op is not modified and has the same meaning as its return value above. \param var_by_load_op is a vector with size play->num_load_op_rec(). \n \n p == 0 \n In this case, The input value of the elements does not matter. Upon return, it is the variable index corresponding the result for each load operator. In the case where the index is zero, the load operator results in a parameter (not a variable). Note that the is no variable with index zero on the tape. \n \n p > 0 \n In this case var_by_load_op is not modified and has the meaning as its return value above. \param p is the lowest order of the Taylor coefficients that are computed during this call. \param q is the highest order of the Taylor coefficients that are computed during this call. \param taylor \n \b Input: For i = 1 , ... , numvar-1, k = 0 , ... , p-1, taylor[ J*i + k] is the k-th order Taylor coefficient corresponding to the i-th variable. \n \n \b Input: For i = 1 , ... , n, k = p , ... , q, taylor[ J*j + k] is the k-th order Taylor coefficient corresponding to the i-th variable (these are the independent varaibles). \n \n \b Output: For i = n+1 , ... , numvar-1, and k = 0 , ... , p-1, taylor[ J*i + k] is the k-th order Taylor coefficient corresponding to the i-th variable. \param compare_change_count Is the count value for changing number and op_index during zero order foward mode. \param compare_change_number If p is non-zero, this value is not changed, otherwise: If compare_change_count is zero, this value is set to zero, otherwise: this value is set to the number of comparision operations that have a different result from when the information in play was recorded. \param compare_change_op_index if p is non-zero, this value is not changed, otherwise: If compare_change_count is zero, this value is set to zero. Otherwise it is the operator index (see forward_next) for the count-th comparision operation that has a different result from when the information in play was recorded. */ template void forward1sweep( std::ostream& s_out, const bool print, const size_t p, const size_t q, const size_t n, const size_t numvar, player* play, const size_t J, Base* taylor, bool* cskip_op, pod_vector& var_by_load_op, size_t compare_change_count, size_t& compare_change_number, size_t& compare_change_op_index ) { // number of directions const size_t r = 1; CPPAD_ASSERT_UNKNOWN( p <= q ); CPPAD_ASSERT_UNKNOWN( J >= q + 1 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); /* */ // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; // operation argument indices const addr_t* arg = CPPAD_NULL; // initialize the comparision operator counter if( p == 0 ) { compare_change_number = 0; compare_change_op_index = 0; } // If this includes a zero calculation, initialize this information pod_vector isvar_by_ind; pod_vector index_by_ind; if( p == 0 ) { size_t i; // this includes order zero calculation, initialize vector indices size_t num = play->num_vec_ind_rec(); if( num > 0 ) { isvar_by_ind.extend(num); index_by_ind.extend(num); for(i = 0; i < num; i++) { index_by_ind[i] = play->GetVecInd(i); isvar_by_ind[i] = false; } } // includes zero order, so initialize conditional skip flags num = play->num_op_rec(); for(i = 0; i < num; i++) cskip_op[i] = false; } // work space used by UserOp. vector user_vx; // empty vecotor vector user_vy; // empty vecotor vector user_tx; // argument vector Taylor coefficients vector user_ty; // result vector Taylor coefficients size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end, user_trace } user_state = user_start; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // length of the text vector (used by CppAD assert macros) const size_t num_text = play->num_text_rec(); // pointer to the beginning of the text vector const char* text = CPPAD_NULL; if( num_text > 0 ) text = play->GetTxt(0); /* */ // temporary indices size_t i, k; // number of orders for this user calculation // (not needed for order zero) const size_t user_q1 = q+1; // variable indices for results vector // (done differently for order zero). vector user_iy; // skip the BeginOp at the beginning of the recording play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD1SWEEP_TRACE Rcout << std::endl; # endif bool more_operators = true; while(more_operators) { // this op play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var); // check if we are skipping this operation while( cskip_op[i_op] ) { if( op == CSumOp ) { // CSumOp has a variable number of arguments play->forward_csum(op, arg, i_op, i_var); } CPPAD_ASSERT_UNKNOWN( op != CSkipOp ); // if( op == CSkipOp ) // { // CSkip has a variable number of arguments // play->forward_cskip(op, arg, i_op, i_var); // } play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); } // action depends on the operator switch( op ) { case AbsOp: forward_abs_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_addpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CExpOp: forward_cond_op( p, q, i_var, arg, num_par, parameter, J, taylor ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op(p, q, i_var, arg[0], J, taylor); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. if( p == 0 ) { forward_cskip_op_0( i_var, arg, num_par, parameter, J, taylor, cskip_op ); } play->forward_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_csum_op( p, q, i_var, arg, num_par, parameter, J, taylor ); play->forward_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case DisOp: forward_dis_op(p, q, r, i_var, arg, J, taylor); break; // ------------------------------------------------- case DivvvOp: forward_divvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_divpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_divvp_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case EqpvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_eqpv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case EqvvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_eqvv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- # if CPPAD_COMPILER_HAS_ERF case ErfOp: CPPAD_ASSERT_UNKNOWN( CPPAD_COMPILER_HAS_ERF ); // 2DO: implement zero order version of this function forward_erf_op(p, q, i_var, arg, parameter, J, taylor); break; # endif // ------------------------------------------------- case ExpOp: forward_exp_op(p, q, i_var, arg[0], J, taylor); break; // --------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // ------------------------------------------------- case LdpOp: if( p == 0 ) { forward_load_p_op_0( play, i_var, arg, parameter, J, taylor, isvar_by_ind.data(), index_by_ind.data(), var_by_load_op.data() ); if( p < q ) forward_load_op( play, op, p+1, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); } else forward_load_op( play, op, p, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); break; // ------------------------------------------------- case LdvOp: if( p == 0 ) { forward_load_v_op_0( play, i_var, arg, parameter, J, taylor, isvar_by_ind.data(), index_by_ind.data(), var_by_load_op.data() ); if( p < q ) forward_load_op( play, op, p+1, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); } else forward_load_op( play, op, p, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); break; // ------------------------------------------------- case LepvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_lepv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; case LevpOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_levp_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case LevvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_levv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case LogOp: forward_log_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case LtpvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_ltpv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; case LtvpOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_ltvp_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case LtvvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_ltvv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case MulvvOp: forward_mulvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_mulpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case NepvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_nepv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case NevvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_nevv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case ParOp: i = p; if( i == 0 ) { forward_par_op_0( i_var, arg, num_par, parameter, J, taylor ); i++; } while(i <= q) { taylor[ i_var * J + i] = Base(0); i++; } break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_powvp_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_powpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PriOp: if( (p == 0) & print ) forward_pri_0(s_out, arg, num_text, text, num_par, parameter, J, taylor ); break; // ------------------------------------------------- case SignOp: // sign(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sign_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case StppOp: if( p == 0 ) { forward_store_pp_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); } break; // ------------------------------------------------- case StpvOp: if( p == 0 ) { forward_store_pv_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); } break; // ------------------------------------------------- case StvpOp: if( p == 0 ) { forward_store_vp_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); } break; // ------------------------------------------------- case StvvOp: if( p == 0 ) { forward_store_vv_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); } break; // ------------------------------------------------- case SubvvOp: forward_subvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_subpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_subvp_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tan_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tanh_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_tx.size() != user_n * user_q1) user_tx.resize(user_n * user_q1); if(user_ty.size() != user_m * user_q1) user_ty.resize(user_m * user_q1); if(user_iy.size() != user_m) user_iy.resize(user_m); user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); CPPAD_ATOMIC_CALL( p, q, user_vx, user_vy, user_tx, user_ty ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base.forward: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(i = 0; i < user_m; i++) if( user_iy[i] > 0 ) for(k = p; k <= q; k++) taylor[ user_iy[i] * J + k ] = user_ty[ i * user_q1 + k ]; # if CPPAD_FORWARD1SWEEP_TRACE user_state = user_trace; # else user_state = user_start; # endif } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); user_tx[user_j * user_q1 + 0] = parameter[ arg[0]]; for(k = 1; k < user_q1; k++) user_tx[user_j * user_q1 + k] = Base(0); ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); for(k = 0; k < user_q1; k++) user_tx[user_j * user_q1 + k] = taylor[ arg[0] * J + k]; ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = 0; user_ty[user_i * user_q1 + 0] = parameter[ arg[0]]; for(k = 1; k < p; k++) user_ty[user_i * user_q1 + k] = Base(0); user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = i_var; for(k = 0; k < p; k++) user_ty[user_i * user_q1 + k] = taylor[ i_var * J + k]; user_i++; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FORWARD1SWEEP_TRACE if( user_state == user_trace ) { user_state = user_start; CPPAD_ASSERT_UNKNOWN( op == UserOp ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 ); for(i = 0; i < user_m; i++) if( user_iy[i] > 0 ) { size_t i_tmp = (i_op + i) - user_m; printOp( Rcout, play, i_tmp, user_iy[i], UsrrvOp, CPPAD_NULL ); Base* Z_tmp = taylor + user_iy[i] * J; printOpResult( Rcout, q + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); Rcout << std::endl; } } Base* Z_tmp = taylor + J * i_var; const addr_t* arg_tmp = arg; if( op == CSumOp ) arg_tmp = arg - arg[-1] - 4; if( op == CSkipOp ) arg_tmp = arg - arg[-1] - 7; if( op != UsrrvOp ) { printOp( Rcout, play, i_op, i_var, op, arg_tmp ); if( NumRes(op) > 0 ) printOpResult( Rcout, q + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); Rcout << std::endl; } } Rcout << std::endl; # else } # endif CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( i_var + 1 == play->num_var_rec() ); if( (p == 0) & (compare_change_count == 0) ) compare_change_number = 0; return; } // preprocessor symbols that are local to this file # undef CPPAD_FORWARD1SWEEP_TRACE # undef CPPAD_ATOMIC_CALL } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sparse_hessian.hpp0000644000176200001440000005477614536067013021225 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_HESSIAN_INCLUDED # define CPPAD_SPARSE_HESSIAN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin sparse_hessian$$ $spell jacobian recomputed CppAD valarray std Bool hes const Taylor cppad cmake colpack $$ $section Sparse Hessian: Easy Driver$$ $index SparseHessian$$ $index hessian, sparse$$ $head Syntax$$ $icode%hes% = %f%.SparseHessian(%x%, %w%) %hes% = %f%.SparseHessian(%x%, %w%, %p%) %n_sweep% = %f%.SparseHessian(%x%, %w%, %p%, %row%, %col%, %hes%, %work%) %$$ $head Purpose$$ We use $latex n$$ for the $cref/domain/seq_property/Domain/$$ size, and $latex m$$ for the $cref/range/seq_property/Range/$$ size of $icode f$$. We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ do denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. The syntax above sets $icode hes$$ to the Hessian $latex \[ H(x) = \dpow{2}{x} \sum_{i=1}^m w_i F_i (x) \] $$ This routine takes advantage of the sparsity of the Hessian in order to reduce the amount of computation necessary. If $icode row$$ and $icode col$$ are present, it also takes advantage of the reduced set of elements of the Hessian that need to be computed. One can use speed tests (e.g. $cref speed_test$$) to verify that results are computed faster than when using the routine $cref Hessian$$. $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/Uses Forward/sparse_hessian/Uses Forward/$$ below). $head x$$ The argument $icode x$$ has prototype $codei% const %VectorBase%& %x% %$$ (see $cref/VectorBase/sparse_hessian/VectorBase/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies that point at which to evaluate the Hessian. $head w$$ The argument $icode w$$ has prototype $codei% const %VectorBase%& %w% %$$ and size $latex m$$. It specifies the value of $latex w_i$$ in the expression for $icode hes$$. The more components of $latex w$$ that are identically zero, the more sparse the resulting Hessian may be (and hence the more efficient the calculation of $icode hes$$ may be). $head p$$ The argument $icode p$$ is optional and has prototype $codei% const %VectorSet%& %p% %$$ (see $cref/VectorSet/sparse_hessian/VectorSet/$$ below) If it has elements of type $code bool$$, its size is $latex n * n$$. If it has elements of type $code std::set$$, its size is $latex n$$ and all its set elements are between zero and $latex n - 1$$. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the Hessian $latex H(x)$$. $pre $$ If this sparsity pattern does not change between calls to $codei SparseHessian$$, it should be faster to calculate $icode p$$ once and pass this argument to $codei SparseHessian$$. In addition, if you specify $icode p$$, CppAD will use the same type of sparsity representation (vectors of $code bool$$ or vectors of $code std::set$$) for its internal calculations. Otherwise, the representation for the internal calculations is unspecified. $head row, col$$ The arguments $icode row$$ and $icode col$$ are optional and have prototype $codei% const %VectorSize%& %row% const %VectorSize%& %col% %$$ (see $cref/VectorSize/sparse_hessian/VectorSize/$$ below). They specify which rows and columns of $latex H (x)$$ are returned and in what order. We use $latex K$$ to denote the value $icode%hes%.size()%$$ which must also equal the size of $icode row$$ and $icode col$$. Furthermore, for $latex k = 0 , \ldots , K-1$$, it must hold that $latex row[k] < n$$ and $latex col[k] < n$$. In addition, all of the $latex (row[k], col[k])$$ pairs must correspond to a true value in the sparsity pattern $icode p$$. $head hes$$ The result $icode hes$$ has prototype $codei% %VectorBase% %hes% %$$ In the case where $icode row$$ and $icode col$$ are not present, the size of $icode hes$$ is $latex n * n$$ and its size is $latex n * n$$. In this case, for $latex i = 0 , \ldots , n - 1 $$ and $latex ell = 0 , \ldots , n - 1$$ $latex \[ hes [ j * n + \ell ] = \DD{ w^{\rm T} F }{ x_j }{ x_\ell } ( x ) \] $$ $pre $$ In the case where the arguments $icode row$$ and $icode col$$ are present, we use $latex K$$ to denote the size of $icode hes$$. The input value of its elements does not matter. Upon return, for $latex k = 0 , \ldots , K - 1$$, $latex \[ hes [ k ] = \DD{ w^{\rm T} F }{ x_j }{ x_\ell } (x) \; , \; \; {\rm where} \; j = row[k] \; {\rm and } \; \ell = col[k] \] $$ $head work$$ If this argument is present, it has prototype $codei% sparse_hessian_work& %work% %$$ This object can only be used with the routines $code SparseHessian$$. During its the first use, information is stored in $icode work$$. This is used to reduce the work done by future calls to $code SparseHessian$$ with the same $icode f$$, $icode p$$, $icode row$$, and $icode col$$. If a future call is made where any of these values have changed, you must first call $icode%work%.clear()%$$ to inform CppAD that this information needs to be recomputed. $subhead color_method$$ The coloring algorithm determines which rows and columns can be computed during the same sweep. This field has prototype $codei% std::string %work%.color_method %$$ This value only matters on the first call to $code sparse_hessian$$ that follows the $icode work$$ constructor or a call to $icode%work%.clear()%$$. $codei% "cppad.symmetric" %$$ This is the default coloring method (after a constructor or $code clear()$$). It takes advantage of the fact that the Hessian matrix is symmetric to find a coloring that requires fewer $cref/sweeps/sparse_hessian/n_sweep/$$. $codei% "cppad.general" %$$ This is the same as the $code "cppad"$$ method for the $cref/sparse_jacobian/sparse_jacobian/work/color_method/$$ calculation. $codei% "colpack.star" %$$ This method requires that $cref colpack_prefix$$ was specified on the $cref/cmake command/cmake/CMake Command/$$ line. It also takes advantage of the fact that the Hessian matrix is symmetric. $head n_sweep$$ The return value $icode n_sweep$$ has prototype $codei% size_t %n_sweep% %$$ It is the number of first order forward sweeps used to compute the requested Hessian values. Each first forward sweep is followed by a second order reverse sweep so it is also the number of reverse sweeps. This is proportional to the total work that $code SparseHessian$$ does, not counting the zero order forward sweep, or the work to combine multiple columns into a single forward-reverse sweep pair. $head VectorBase$$ The type $icode VectorBase$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Base$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head VectorSet$$ The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code bool$$ or $code std::set$$; see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion of the difference. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $subhead Restrictions$$ If $icode VectorSet$$ has elements of $code std::set$$, then $icode%p%[%i%]%$$ must return a reference (not a copy) to the corresponding set. According to section 26.3.2.3 of the 1998 C++ standard, $code std::valarray< std::set >$$ does not satisfy this condition. $head VectorSize$$ The type $icode VectorSize$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code size_t$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Uses Forward$$ After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After a call to any of the sparse Hessian routines, the zero order Taylor coefficients correspond to $icode%f%.Forward(0, %x%)%$$ and the other coefficients are unspecified. $children% example/sparse_hessian.cpp% example/sub_sparse_hes.cpp %$$ $head Example$$ The routine $cref sparse_hessian.cpp$$ is examples and tests of $code sparse_hessian$$. It return $code true$$, if it succeeds and $code false$$ otherwise. $head Subset Hessian$$ The routine $cref sub_sparse_hes.cpp$$ is examples and test for computing a sparse Hessian for a subset of the variables. It return $code true$$, if it succeeds and $code false$$ otherwise. $end ----------------------------------------------------------------------------- */ # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sparse_hessian.hpp Sparse Hessian driver routine and helper functions. */ // =========================================================================== /*! class used by SparseHessian to hold information so it does not need to be recomputed. */ class sparse_hessian_work { public: /// Coloring method: "cppad", or "colpack" /// (this field is set by user) std::string color_method; /// row and column indicies for return values /// (some may be reflected by star coloring algorithm) CppAD::vector row; CppAD::vector col; /// indices that sort the user row and col arrays by color CppAD::vector order; /// results of the coloring algorithm CppAD::vector color; /// constructor sparse_hessian_work(void) : color_method("cppad.symmetric") { } /// inform CppAD that this information needs to be recomputed void clear(void) { color_method = "cppad.symmetric"; row.clear(); col.clear(); order.clear(); color.clear(); } }; // =========================================================================== /*! Private helper function that does computation for all Sparse Hessian cases. \tparam Base is the base type for the recording that is stored in this ADFun. \tparam VectorSize is \c sparse_pack, \c sparse_set or \c sparse_list. \param x [in] is a vector specifing the point at which to compute the Hessian. \param w [in] is the weighting vector that defines a scalar valued function by a weighted sum of the components of the vector valued function $latex F(x)$$. \param sparsity [in] is the sparsity pattern for the Hessian that we are calculating. \param user_row [in] is the vector of row indices for the returned Hessian values. \param user_col [in] is the vector of columns indices for the returned Hessian values. It must have the same size as user_row. \param hes [out] is the vector of Hessian values. It must have the same size as user_row. The return value hes[k] is the second partial of \f$ w^{\rm T} F(x)\f$ with respect to the row[k] and col[k] component of \f$ x\f$. \param work This structure contains information that is computed by \c SparseHessianCompute. If the sparsity pattern, \c row vector, or \c col vectors are not the same between calls to \c SparseHessianCompute, \c work.clear() must be called to reinitialize \c work. \return Is the number of first order forward sweeps used to compute the requested Hessian values. (This is also equal to the number of second order reverse sweeps.) The total work, not counting the zero order forward sweep, or the time to combine computations, is proportional to this return value. */ template template size_t ADFun::SparseHessianCompute( const VectorBase& x , const VectorBase& w , VectorSet& sparsity , const VectorSize& user_row , const VectorSize& user_col , VectorBase& hes , sparse_hessian_work& work ) { using CppAD::vectorBool; size_t i, k, ell; CppAD::vector& row(work.row); CppAD::vector& col(work.col); CppAD::vector& color(work.color); CppAD::vector& order(work.order); size_t n = Domain(); // some values const Base zero(0); const Base one(1); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector(); // number of components of Hessian that are required size_t K = hes.size(); CPPAD_ASSERT_UNKNOWN( user_row.size() == K ); CPPAD_ASSERT_UNKNOWN( user_col.size() == K ); CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == n ); CPPAD_ASSERT_UNKNOWN( color.size() == 0 || color.size() == n ); CPPAD_ASSERT_UNKNOWN( row.size() == 0 || row.size() == K ); CPPAD_ASSERT_UNKNOWN( col.size() == 0 || col.size() == K ); // Point at which we are evaluating the Hessian Forward(0, x); // check for case where nothing (except Forward above) to do if( K == 0 ) return 0; // Rows of the Hessian (i below) correspond to the forward mode index // and columns (j below) correspond to the reverse mode index. if( color.size() == 0 ) { CPPAD_ASSERT_UNKNOWN( sparsity.n_set() == n ); CPPAD_ASSERT_UNKNOWN( sparsity.end() == n ); // copy user rwo and col to work space row.resize(K); col.resize(K); for(k = 0; k < K; k++) { row[k] = user_row[k]; col[k] = user_col[k]; } // execute coloring algorithm color.resize(n); if( work.color_method == "cppad.general" ) color_general_cppad(sparsity, row, col, color); else if( work.color_method == "cppad.symmetric" ) color_symmetric_cppad(sparsity, row, col, color); else if( work.color_method == "colpack.star" ) { # if CPPAD_HAS_COLPACK color_symmetric_colpack(sparsity, row, col, color); # else CPPAD_ASSERT_KNOWN( false, "SparseHessian: work.color_method = colpack.star" "and colpack_prefix missing from cmake command line." ); # endif } else { CPPAD_ASSERT_KNOWN( false, "SparseHessian: work.color_method is not valid." ); } // put sorting indices in color order VectorSize key(K); order.resize(K); for(k = 0; k < K; k++) key[k] = color[ row[k] ]; index_sort(key, order); } size_t n_color = 1; for(ell = 0; ell < n; ell++) if( color[ell] < n ) n_color = std::max(n_color, color[ell] + 1); // direction vector for calls to forward (rows of the Hessian) VectorBase u(n); // location for return values from reverse (columns of the Hessian) VectorBase ddw(2 * n); // initialize the return value for(k = 0; k < K; k++) hes[k] = zero; // loop over colors k = 0; for(ell = 0; ell < n_color; ell++) { CPPAD_ASSERT_UNKNOWN( color[ row[ order[k] ] ] == ell ); // combine all rows with this color for(i = 0; i < n; i++) { u[i] = zero; if( color[i] == ell ) u[i] = one; } // call forward mode for all these rows at once Forward(1, u); // evaluate derivative of w^T * F'(x) * u ddw = Reverse(2, w); // set the corresponding components of the result while( k < K && color[ row[ order[k] ] ] == ell ) { hes[ order[k] ] = ddw[ col[ order[k] ] * 2 + 1 ]; k++; } } return n_color; } // =========================================================================== // Public Member Functions // =========================================================================== /*! Compute user specified subset of a sparse Hessian. The C++ source code corresponding to this operation is \verbatim SparceHessian(x, w, p, row, col, hes, work) \endverbatim \tparam Base is the base type for the recording that is stored in this ADFun. \tparam VectorSize is a simple vector class with elements of type \c size_t. \param x [in] is a vector specifing the point at which to compute the Hessian. \param w [in] is the weighting vector that defines a scalar valued function by a weighted sum of the components of the vector valued function $latex F(x)$$. \param p [in] is the sparsity pattern for the Hessian that we are calculating. \param row [in] is the vector of row indices for the returned Hessian values. \param col [in] is the vector of columns indices for the returned Hessian values. It must have the same size are r. \param hes [out] is the vector of Hessian values. It must have the same size are r. The return value hes[k] is the second partial of \f$ w^{\rm T} F(x)\f$ with respect to the row[k] and col[k] component of \f$ x\f$. \param work This structure contains information that is computed by \c SparseHessianCompute. If the sparsity pattern, \c row vector, or \c col vectors are not the same between calls to \c SparseHessian, \c work.clear() must be called to reinitialize \c work. \return Is the number of first order forward sweeps used to compute the requested Hessian values. (This is also equal to the number of second order reverse sweeps.) The total work, not counting the zero order forward sweep, or the time to combine computations, is proportional to this return value. */ template template size_t ADFun::SparseHessian( const VectorBase& x , const VectorBase& w , const VectorSet& p , const VectorSize& row , const VectorSize& col , VectorBase& hes , sparse_hessian_work& work ) { size_t n = Domain(); # ifndef NDEBUG size_t k, K = hes.size(); CPPAD_ASSERT_KNOWN( size_t(x.size()) == n , "SparseHessian: size of x not equal domain dimension for f." ); CPPAD_ASSERT_KNOWN( size_t(row.size()) == K && size_t(col.size()) == K , "SparseHessian: either r or c does not have the same size as ehs." ); CPPAD_ASSERT_KNOWN( work.color.size() == 0 || work.color.size() == n, "SparseHessian: invalid value in work." ); for(k = 0; k < K; k++) { CPPAD_ASSERT_KNOWN( row[k] < n, "SparseHessian: invalid value in r." ); CPPAD_ASSERT_KNOWN( col[k] < n, "SparseHessian: invalid value in c." ); } if( work.color.size() != 0 ) for(size_t j = 0; j < n; j++) CPPAD_ASSERT_KNOWN( work.color[j] <= n, "SparseHessian: invalid value in work." ); # endif typedef typename VectorSet::value_type Set_type; typedef typename internal_sparsity::pattern_type Pattern_type; Pattern_type s; if( work.color.size() == 0 ) { bool transpose = false; sparsity_user2internal(s, p, n, n, transpose); } size_t n_sweep = SparseHessianCompute(x, w, s, row, col, hes, work); return n_sweep; } /*! Compute a sparse Hessian. The C++ source code coresponding to this operation is \verbatim hes = SparseHessian(x, w, p) \endverbatim \tparam Base is the base type for the recording that is stored in this ADFun. \param x [in] is a vector specifing the point at which to compute the Hessian. \param w [in] The Hessian is computed for a weighted sum of the components of the function corresponding to this ADFun object. The argument \a w specifies the weights for each component. It must have size equal to the range dimension for this ADFun object. \param p [in] is a sparsity pattern for the Hessian. \return Will be a vector of size \c n * n containing the Hessian of at the point specified by \a x (where \c n is the domain dimension for this ADFun object). */ template template VectorBase ADFun::SparseHessian( const VectorBase& x, const VectorBase& w, const VectorSet& p ) { size_t i, j, k; size_t n = Domain(); VectorBase hes(n * n); CPPAD_ASSERT_KNOWN( size_t(x.size()) == n, "SparseHessian: size of x not equal domain size for f." ); typedef typename VectorSet::value_type Set_type; typedef typename internal_sparsity::pattern_type Pattern_type; // initialize the return value as zero Base zero(0); for(i = 0; i < n; i++) for(j = 0; j < n; j++) hes[i * n + j] = zero; // arguments to SparseHessianCompute Pattern_type s; CppAD::vector row; CppAD::vector col; sparse_hessian_work work; bool transpose = false; sparsity_user2internal(s, p, n, n, transpose); k = 0; for(i = 0; i < n; i++) { s.begin(i); j = s.next_element(); while( j != s.end() ) { row.push_back(i); col.push_back(j); k++; j = s.next_element(); } } size_t K = k; VectorBase H(K); // now we have folded this into the following case SparseHessianCompute(x, w, s, row, col, H, work); // now set the non-zero return values for(k = 0; k < K; k++) hes[ row[k] * n + col[k] ] = H[k]; return hes; } /*! Compute a sparse Hessian The C++ source code coresponding to this operation is \verbatim hes = SparseHessian(x, w) \endverbatim \tparam Base is the base type for the recording that is stored in this ADFun object. The argument \a w specifies the weights for each component. It must have size equal to the range dimension for this ADFun object. \return Will be a vector of size \c n * n containing the Hessian of at the point specified by \a x (where \c n is the domain dimension for this ADFun object). */ template template VectorBase ADFun::SparseHessian(const VectorBase &x, const VectorBase &w) { size_t i, j, k; typedef CppAD::vectorBool VectorBool; size_t m = Range(); size_t n = Domain(); // determine the sparsity pattern p for Hessian of w^T F VectorBool r(n * n); for(j = 0; j < n; j++) { for(k = 0; k < n; k++) r[j * n + k] = false; r[j * n + j] = true; } ForSparseJac(n, r); // VectorBool s(m); for(i = 0; i < m; i++) s[i] = w[i] != 0; VectorBool p = RevSparseHes(n, s); // compute sparse Hessian return SparseHessian(x, w, p); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/num_skip.hpp0000644000176200001440000000545214536067013020026 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_NUM_SKIP_INCLUDED # define CPPAD_NUM_SKIP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin number_skip$$ $spell optimizer var taylor_ $$ $index number_skip$$ $index number, skip variables$$ $index skip, number variables$$ $index variables, skip$$ $section Number of Variables that Can be Skipped$$ $head Syntax$$ $icode%n% = %f%.number_skip()%$$ $subhead See Also$$ $cref seq_property$$ $head Purpose$$ The $cref/conditional expressions/CondExp/$$ use either the $cref/if_true/CondExp/$$ or $cref/if_false/CondExp/$$. This leads to the fact that some terms only need to be evaluated depending on the value of the comparison in the conditional expression. The $cref optimize$$ option is capable of detecting some of these case and determining variables that can be skipped. This routine returns the number such variables. $head n$$ The return value $icode n$$ has type $code size_t$$ is the number of variables that the optimizer has determined can be skipped (given the independent variable values specified by the previous call to $cref/f.Forward/Forward/$$ for order zero). $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ $children% example/number_skip.cpp %$$ $head Example$$ The file $cref number_skip.cpp$$ contains an example and test of this function. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { // This routine is not const becasue it runs through the operations sequence // 2DO: compute this value during zero order forward operations. template size_t ADFun::number_skip(void) { // must pass through operation sequence to map operations to variables OpCode op; size_t i_op; size_t i_var; const addr_t* arg; // number of variables skipped size_t n_skip = 0; // start playback play_.forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN(op == BeginOp) while(op != EndOp) { // next op play_.forward_next(op, arg, i_op, i_var); if( op == CSumOp) play_.forward_csum(op, arg, i_op, i_var); else if (op == CSkipOp) play_.forward_cskip(op, arg, i_op, i_var); // if( cskip_op_[i_op] ) n_skip += NumRes(op); } return n_skip; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/color_general.hpp0000644000176200001440000002120114536067013021002 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_COLOR_GENERAL_INCLUDED # define CPPAD_COLOR_GENERAL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file color_general.hpp Coloring algorithm for a general sparse matrix. */ // -------------------------------------------------------------------------- /*! Determine which rows of a general sparse matrix can be computed together; i.e., do not have non-zero entries with the same column index. \tparam VectorSize is a simple vector class with elements of type size_t. \tparam VectorSet is an unspecified type with the exception that it must support the operations under pattern and the following operations where p is a VectorSet object: \n VectorSet p Constructs a new vector of sets object. \n p.resize(ns, ne) resizes \c p to \c ns sets with elements between zero \c ne. All of the \c ns sets are initially empty. \n p.add_element(s, e) add element \c e to set with index \c s. \param pattern [in] Is a representation of the sparsity pattern for the matrix. Note that color_general does not change the values in pattern, but it is not const because its iterator facility modifies some of its internal data. \n m = pattern.n_set() \n sets \c m to the number of rows in the sparse matrix. All of the row indices are less than this value. \n n = pattern.end() \n sets \c n to the number of columns in the sparse matrix. All of the column indices are less than this value. \n pattern.begin(i) instructs the iterator facility to start iterating over columns in the i-th row of the sparsity pattern. \n j = pattern.next_element() Sets j to the next possibly non-zero column in the row specified by the previous call to pattern.begin. If there are no more such columns, the value pattern.end() is returned. \param row [in] is a vector specifying which row indices to compute. \param col [in] is a vector, with the same size as row, that specifies which column indices to compute. For each valid index k, the index pair (row[k], col[k]) must be present in the sparsity pattern. It may be that some entries in the sparsity pattern do not need to be computed; i.e, do not appear in the set of (row[k], col[k]) entries. \param color [out] is a vector with size m. The input value of its elements does not matter. Upon return, it is a coloring for the rows of the sparse matrix. \n \n If for some i, color[i] == m, then the i-th row does not appear in the vector row. Otherwise, color[i] < m. \n \n Suppose two differen rows, i != r have the same color and column index j is such that both of the pairs (i, j) and (r, j) appear in the sparsity pattern. It follows that neither of these pairs appear in the set of (row[k], col[k]) entries. \n \n This routine tries to minimize, with respect to the choice of colors, the maximum, with respct to k, of color[ row[k] ] (not counting the indices k for which row[k] == m). */ template void color_general_cppad( VectorSet& pattern , const VectorSize& row , const VectorSize& col , CppAD::vector& color ) { size_t i, j, k, ell, r; size_t K = row.size(); size_t m = pattern.n_set(); size_t n = pattern.end(); CPPAD_ASSERT_UNKNOWN( col.size() == K ); CPPAD_ASSERT_UNKNOWN( color.size() == m ); // We define the set of rows, columns, and pairs that appear // by the set ( row[k], col[k] ) for k = 0, ... , K-1. // initialize rows that appear CppAD::vector row_appear(m); for(i = 0; i < m; i++) row_appear[i] = false; // rows and columns that appear VectorSet c2r_appear, r2c_appear; c2r_appear.resize(n, m); r2c_appear.resize(m, n); for(k = 0; k < K; k++) { CPPAD_ASSERT_UNKNOWN( pattern.is_element(row[k], col[k]) ); row_appear[ row[k] ] = true; c2r_appear.add_element(col[k], row[k]); r2c_appear.add_element(row[k], col[k]); } // for each column, which rows are non-zero and do not appear VectorSet not_appear; not_appear.resize(n, m); for(i = 0; i < m; i++) { pattern.begin(i); j = pattern.next_element(); while( j != pattern.end() ) { if( ! c2r_appear.is_element(j , i) ) not_appear.add_element(j, i); j = pattern.next_element(); } } // initial coloring color.resize(m); ell = 0; for(i = 0; i < m; i++) { if( row_appear[i] ) color[i] = ell++; else color[i] = m; } /* See GreedyPartialD2Coloring Algorithm Section 3.6.2 of Graph Coloring in Optimization Revisited by Assefaw Gebremedhin, Fredrik Maane, Alex Pothen The algorithm above was modified (by Brad Bell) to take advantage of the fact that only the entries (subset of the sparsity pattern) specified by row and col need to be computed. */ CppAD::vector forbidden(m); for(i = 1; i < m; i++) // for each row that appears if( color[i] < m ) { // initial all colors as ok for this row // (value of forbidden for ell > initial color[i] does not matter) for(ell = 0; ell <= color[i]; ell++) forbidden[ell] = false; // ----------------------------------------------------- // Forbid colors for which this row would destroy results: // // for each column that is non-zero for this row pattern.begin(i); j = pattern.next_element(); while( j != pattern.end() ) { // for each row that appears with this column c2r_appear.begin(j); r = c2r_appear.next_element(); while( r != c2r_appear.end() ) { // if this is not the same row, forbid its color if( (r < i) & (color[r] < m) ) forbidden[ color[r] ] = true; r = c2r_appear.next_element(); } j = pattern.next_element(); } // ----------------------------------------------------- // Forbid colors that destroy results needed for this row. // // for each column that appears with this row r2c_appear.begin(i); j = r2c_appear.next_element(); while( j != r2c_appear.end() ) { // For each row that is non-zero for this column // (the appear rows have already been checked above). not_appear.begin(j); r = not_appear.next_element(); while( r != not_appear.end() ) { // if this is not the same row, forbid its color if( (r < i) & (color[r] < m) ) forbidden[ color[r] ] = true; r = not_appear.next_element(); } j = r2c_appear.next_element(); } // pick the color with smallest index ell = 0; while( forbidden[ell] ) { ell++; CPPAD_ASSERT_UNKNOWN( ell <= color[i] ); } color[i] = ell; } return; } # if CPPAD_HAS_COLPACK /*! Colpack version of determining which rows of a sparse matrix can be computed together. \copydetails color_general */ template void color_general_colpack( VectorSet& pattern , const VectorSize& row , const VectorSize& col , CppAD::vector& color ) { size_t i, j, k; size_t m = pattern.n_set(); size_t n = pattern.end(); // Determine number of non-zero entries in each row CppAD::vector n_nonzero(m); size_t n_nonzero_total = 0; for(i = 0; i < m; i++) { n_nonzero[i] = 0; pattern.begin(i); j = pattern.next_element(); while( j != pattern.end() ) { n_nonzero[i]++; j = pattern.next_element(); } n_nonzero_total += n_nonzero[i]; } // Allocate memory and fill in Adolc sparsity pattern CppAD::vector adolc_pattern(m); CppAD::vector adolc_memory(m + n_nonzero_total); size_t i_memory = 0; for(i = 0; i < m; i++) { adolc_pattern[i] = adolc_memory.data() + i_memory; adolc_pattern[i][0] = n_nonzero[i]; pattern.begin(i); j = pattern.next_element(); k = 1; while(j != pattern.end() ) { adolc_pattern[i][k++] = j; j = pattern.next_element(); } CPPAD_ASSERT_UNKNOWN( k == 1 + n_nonzero[i] ); i_memory += k; } CPPAD_ASSERT_UNKNOWN( i_memory == m + n_nonzero_total ); // Must use an external routine for this part of the calculation because // ColPack/ColPackHeaders.h has as 'using namespace std' at global level. cppad_colpack_general(color, m, n, adolc_pattern); return; } # endif // CPPAD_HAS_COLPACK } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/ad_fun.hpp0000644000176200001440000004373014536067013017436 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_AD_FUN_INCLUDED # define CPPAD_AD_FUN_INCLUDED #include #include /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ADFun$$ $spell xk Ind bool taylor_ sizeof const std ind_taddr_ dep_taddr_ $$ $spell $$ $section ADFun Objects$$ $index ADFun, object$$ $index object, ADFun$$ $head Purpose$$ An AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$ is stored in an $code ADFun$$ object by its $cref FunConstruct$$. The $code ADFun$$ object can then be used to calculate function values, derivative values, and other values related to the corresponding function. $childtable% cppad/local/independent.hpp% cppad/local/fun_construct.hpp% cppad/local/dependent.hpp% cppad/local/abort_recording.hpp% omh/seq_property.omh% cppad/local/fun_eval.hpp% cppad/local/drivers.hpp% cppad/local/fun_check.hpp% cppad/local/optimize.hpp% omh/check_for_nan.omh %$$ $end */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file ad_fun.hpp File used to define the ADFun class. */ /*! Class used to hold function objects \tparam Base A function object has a recording of AD operations. It does it calculations using \c Base operations. */ template class ADFun { // ------------------------------------------------------------ // Private member variables private: /// Has this ADFun object been optmized bool has_been_optimized_; /// Check for nan's and report message to user (default value is true). bool check_for_nan_; /// If zero, ignoring comparison operators. Otherwise is the /// compare change count at which to store the operator index. size_t compare_change_count_; /// If compare_change_count_ is zero, compare_change_number_ is also zero. /// Otherwise, it is set to the number of comparison operations that had a /// different result during the subsequent zero order forward. size_t compare_change_number_; /// If compare_change_count is zero, compare_change_op_index_ is also /// zero. Otherwise it is the operator index for the comparison operator //// that corresponded to the number changing from count-1 to count. size_t compare_change_op_index_; /// number of orders stored in taylor_ size_t num_order_taylor_; /// maximum number of orders that will fit in taylor_ size_t cap_order_taylor_; /// number of directions stored in taylor_ size_t num_direction_taylor_; /// number of variables in the recording (play_) size_t num_var_tape_; /// tape address for the independent variables CppAD::vector ind_taddr_; /// tape address and parameter flag for the dependent variables CppAD::vector dep_taddr_; /// which dependent variables are actually parameters CppAD::vector dep_parameter_; /// results of the forward mode calculations pod_vector taylor_; /// which operations can be conditionally skipped /// Set during forward pass of order zero pod_vector cskip_op_; /// Variable on the tape corresponding to each vecad load operation /// (if zero, the operation corresponds to a parameter). pod_vector load_op_; /// the operation sequence corresponding to this object player play_; /// Packed results of the forward mode Jacobian sparsity calculations. /// for_jac_sparse_pack_.n_set() != 0 implies other sparsity results /// are empty sparse_pack for_jac_sparse_pack_; /// Set results of the forward mode Jacobian sparsity calculations /// for_jac_sparse_set_.n_set() != 0 implies for_sparse_pack_ is empty. CPPAD_INTERNAL_SPARSE_SET for_jac_sparse_set_; // ------------------------------------------------------------ // Private member functions /// change the operation sequence corresponding to this object template void Dependent(ADTape *tape, const ADvector &y); // ------------------------------------------------------------ // vector of bool version of ForSparseJac // (see doxygen in for_sparse_jac.hpp) template void ForSparseJacCase( bool set_type , bool transpose , size_t q , const VectorSet& r , VectorSet& s ); // vector of std::set version of ForSparseJac // (see doxygen in for_sparse_jac.hpp) template void ForSparseJacCase( const std::set& set_type , bool transpose , size_t q , const VectorSet& r , VectorSet& s ); // ------------------------------------------------------------ // vector of bool version of RevSparseJac // (see doxygen in rev_sparse_jac.hpp) template void RevSparseJacCase( bool set_type , bool transpose , bool nz_compare, size_t p , const VectorSet& s , VectorSet& r ); // vector of std::set version of RevSparseJac // (see doxygen in rev_sparse_jac.hpp) template void RevSparseJacCase( const std::set& set_type , bool transpose , bool nz_compare, size_t p , const VectorSet& s , VectorSet& r ); // ------------------------------------------------------------ // vector of bool version of RevSparseHes // (see doxygen in rev_sparse_hes.hpp) template void RevSparseHesCase( bool set_type , bool transpose , size_t q , const VectorSet& s , VectorSet& h ); // vector of std::set version of RevSparseHes // (see doxygen in rev_sparse_hes.hpp) template void RevSparseHesCase( const std::set& set_type , bool transpose , size_t q , const VectorSet& s , VectorSet& h ); // ------------------------------------------------------------ // Forward mode version of SparseJacobian // (see doxygen in sparse_jacobian.hpp) template size_t SparseJacobianFor( const VectorBase& x , VectorSet& p_transpose , const VectorSize& row , const VectorSize& col , VectorBase& jac , sparse_jacobian_work& work ); // Reverse mode version of SparseJacobian // (see doxygen in sparse_jacobian.hpp) template size_t SparseJacobianRev( const VectorBase& x , VectorSet& p , const VectorSize& row , const VectorSize& col , VectorBase& jac , sparse_jacobian_work& work ); // ------------------------------------------------------------ // combined sparse_set, sparse_list and sparse_pack version of // SparseHessian (see doxygen in sparse_hessian.hpp) template size_t SparseHessianCompute( const VectorBase& x , const VectorBase& w , VectorSet& sparsity , const VectorSize& row , const VectorSize& col , VectorBase& hes , sparse_hessian_work& work ); // ------------------------------------------------------------ public: #include "kasper.hpp" /// copy constructor ADFun(const ADFun& g) : num_var_tape_(0) { CppAD::ErrorHandler::Call( true, __LINE__, __FILE__, "ADFun(const ADFun& g)", "Attempting to use the ADFun copy constructor.\n" "Perhaps you are passing an ADFun object " "by value instead of by reference." ); } /// default constructor ADFun(void); // assignment operator // (see doxygen in fun_construct.hpp) void operator=(const ADFun& f); /// sequence constructor template ADFun(const ADvector &x, const ADvector &y); /// destructor ~ADFun(void) { } /// set value of check_for_nan_ void check_for_nan(bool value) { check_for_nan_ = value; } bool check_for_nan(void) const { return check_for_nan_; } /// assign a new operation sequence template void Dependent(const ADvector &x, const ADvector &y); /// forward mode user API, one order multiple directions. template VectorBase Forward(size_t q, size_t r, const VectorBase& x); /// forward mode user API, multiple directions one order. template VectorBase Forward(size_t q, const VectorBase& x, std::ostream& s = Rcout ); /// reverse mode sweep template VectorBase Reverse(size_t p, const VectorBase &v); /// kaspers reverse mode sweep template void myReverse(size_t p, const VectorBase &v, size_t dep_var_index, VectorBase &value); // forward mode Jacobian sparsity // (see doxygen documentation in for_sparse_jac.hpp) template VectorSet ForSparseJac( size_t q, const VectorSet &r, bool transpose = false ); // reverse mode Jacobian sparsity // (see doxygen documentation in rev_sparse_jac.hpp) template VectorSet RevSparseJac( size_t q, const VectorSet &s, bool transpose = false, bool nz_compare = false ); // reverse mode Hessian sparsity // (see doxygen documentation in rev_sparse_hes.hpp) template VectorSet RevSparseHes( size_t q, const VectorSet &s, bool transpose = false ); /// amount of memory used for Jacobain sparsity pattern size_t size_forward_bool(void) const { return for_jac_sparse_pack_.memory(); } /// free memory used for Jacobain sparsity pattern void size_forward_bool(size_t zero) { CPPAD_ASSERT_KNOWN( zero == 0, "size_forward_bool: argument not equal to zero" ); for_jac_sparse_pack_.resize(0, 0); } /// total number of elements used for Jacobian sparsity pattern size_t size_forward_set(void) const { return for_jac_sparse_set_.number_elements(); } /// free memory used for Jacobain sparsity pattern void size_forward_set(size_t zero) { CPPAD_ASSERT_KNOWN( zero == 0, "size_forward_bool: argument not equal to zero" ); for_jac_sparse_set_.resize(0, 0); } /// number of operators in the operation sequence size_t size_op(void) const { return play_.num_op_rec(); } /// number of operator arguments in the operation sequence size_t size_op_arg(void) const { return play_.num_op_arg_rec(); } /// amount of memory required for the operation sequence size_t size_op_seq(void) const { return play_.Memory(); } /// number of parameters in the operation sequence size_t size_par(void) const { return play_.num_par_rec(); } /// number taylor coefficient orders calculated size_t size_order(void) const { return num_order_taylor_; } /// number taylor coefficient directions calculated size_t size_direction(void) const { return num_direction_taylor_; } /// number of characters in the operation sequence size_t size_text(void) const { return play_.num_text_rec(); } /// number of variables in opertion sequence size_t size_var(void) const { return num_var_tape_; } /// number of VecAD indices in the operation sequence size_t size_VecAD(void) const { return play_.num_vec_ind_rec(); } /// set number of orders currently allocated (user API) void capacity_order(size_t c); /// set number of orders and directions currently allocated void capacity_order(size_t c, size_t r); /// number of variables in conditional expressions that can be skipped size_t number_skip(void); /// number of independent variables size_t Domain(void) const { return ind_taddr_.size(); } /// number of dependent variables size_t Range(void) const { return dep_taddr_.size(); } /// is variable a parameter bool Parameter(size_t i) { CPPAD_ASSERT_KNOWN( i < dep_taddr_.size(), "Argument to Parameter is >= dimension of range space" ); return dep_parameter_[i]; } /// Deprecated: number of comparison operations that changed /// for the previous zero order forward (than when function was recorded) size_t CompareChange(void) const { return compare_change_number_; } /// count as which to store operator index void compare_change_count(size_t count) { compare_change_count_ = count; compare_change_number_ = 0; compare_change_op_index_ = 0; } /// number of comparison operations that changed size_t compare_change_number(void) const { return compare_change_number_; } /// operator index for the count-th comparison change size_t compare_change_op_index(void) const { if( has_been_optimized_ ) return 0; return compare_change_op_index_; } /// calculate entire Jacobian template VectorBase Jacobian(const VectorBase &x); /// calculate Hessian for one component of f template VectorBase Hessian(const VectorBase &x, const VectorBase &w); template VectorBase Hessian(const VectorBase &x, size_t i); /// forward mode calculation of partial w.r.t one domain component template VectorBase ForOne( const VectorBase &x , size_t j ); /// reverse mode calculation of derivative of one range component template VectorBase RevOne( const VectorBase &x , size_t i ); /// forward mode calculation of a subset of second order partials template VectorBase ForTwo( const VectorBase &x , const VectorSize_t &J , const VectorSize_t &K ); /// reverse mode calculation of a subset of second order partials template VectorBase RevTwo( const VectorBase &x , const VectorSize_t &I , const VectorSize_t &J ); /// calculate sparse Jacobians template VectorBase SparseJacobian( const VectorBase &x ); template VectorBase SparseJacobian( const VectorBase &x , const VectorSet &p ); template size_t SparseJacobianForward( const VectorBase& x , const VectorSet& p , const VectorSize& r , const VectorSize& c , VectorBase& jac , sparse_jacobian_work& work ); template size_t SparseJacobianReverse( const VectorBase& x , const VectorSet& p , const VectorSize& r , const VectorSize& c , VectorBase& jac , sparse_jacobian_work& work ); /// calculate sparse Hessians template VectorBase SparseHessian( const VectorBase& x , const VectorBase& w ); template VectorBase SparseHessian( const VectorBase& x , const VectorBase& w , const VectorBool& p ); template size_t SparseHessian( const VectorBase& x , const VectorBase& w , const VectorSet& p , const VectorSize& r , const VectorSize& c , VectorBase& hes , sparse_hessian_work& work ); // Optimize the tape // (see doxygen documentation in optimize.hpp) void optimize(const std::string& options = "no_conditional_skip"); // ------------------- Deprecated ----------------------------- /// deprecated: assign a new operation sequence template void Dependent(const ADvector &y); /// Deprecated: number of variables in opertion sequence size_t Size(void) const { return num_var_tape_; } /// Deprecated: # taylor_ coefficients currently stored /// (per variable,direction) size_t Order(void) const { return num_order_taylor_ - 1; } /// Deprecated: amount of memory for this object /// Note that an approximation is used for the std::set memory size_t Memory(void) const { size_t pervar = cap_order_taylor_ * sizeof(Base) + for_jac_sparse_pack_.memory() + 3 * sizeof(size_t) * for_jac_sparse_set_.number_elements(); size_t total = num_var_tape_ * pervar + play_.Memory(); return total; } /// Deprecated: # taylor_ coefficient orderss stored /// (per variable,direction) size_t taylor_size(void) const { return num_order_taylor_; } /// Deprecated: Does this AD operation sequence use /// VecAD::reference operands bool use_VecAD(void) const { return play_.num_vec_ind_rec() > 0; } /// Deprecated: # taylor_ coefficient orders calculated /// (per variable,direction) size_t size_taylor(void) const { return num_order_taylor_; } /// Deprecated: set number of orders currently allocated /// (per variable,direction) void capacity_taylor(size_t per_var); }; // --------------------------------------------------------------------------- } // END_CPPAD_NAMESPACE // non-user interfaces # include # include # include # include # include # include # include // user interfaces # include # include # include # include # include # include # include # include # include # include # endif TMB/inst/include/cppad/local/mul_op.hpp0000644000176200001440000002277114536067013017477 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_MUL_OP_INCLUDED # define CPPAD_MUL_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file mul_op.hpp Forward and reverse mode calculations for z = x * y. */ // --------------------------- Mulvv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = MulvvOp. The C++ source code corresponding to this operation is \verbatim z = x * y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op */ template inline void forward_mulvv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; size_t k; for(size_t d = p; d <= q; d++) { z[d] = Base(0); for(k = 0; k <= d; k++) z[d] += x[d-k] * y[k]; } } /*! Multiple directions forward mode Taylor coefficients for op = MulvvOp. The C++ source code corresponding to this operation is \verbatim z = x * y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op_dir */ template inline void forward_mulvv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + arg[0] * num_taylor_per_var; Base* y = taylor + arg[1] * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; size_t k, ell, m; for(ell = 0; ell < r; ell++) { m = (q-1)*r + ell + 1; z[m] = x[0] * y[m] + x[m] * y[0]; for(k = 1; k < q; k++) z[m] += x[(q-k-1)*r + ell + 1] * y[(k-1)*r + ell + 1]; } } /*! Compute zero order forward mode Taylor coefficients for result of op = MulvvOp. The C++ source code corresponding to this operation is \verbatim z = x * y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op_0 */ template inline void forward_mulvv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x[0] * y[0]; } /*! Compute reverse mode partial derivatives for result of op = MulvvOp. The C++ source code corresponding to this operation is \verbatim z = x * y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails reverse_binary_op */ template inline void reverse_mulvv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Arguments const Base* x = taylor + arg[0] * cap_order; const Base* y = taylor + arg[1] * cap_order; // Partial derivatives corresponding to arguments and result Base* px = partial + arg[0] * nc_partial; Base* py = partial + arg[1] * nc_partial; Base* pz = partial + i_z * nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; // number of indices to access size_t j = d + 1; size_t k; while(j) { --j; for(k = 0; k <= j; k++) { px[j-k] += pz[j] * y[k]; py[k] += pz[j] * x[j-k]; } } } // --------------------------- Mulpv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = MulpvOp. The C++ source code corresponding to this operation is \verbatim z = x * y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op */ template inline void forward_mulpv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; // Paraemter value Base x = parameter[ arg[0] ]; for(size_t d = p; d <= q; d++) z[d] = x * y[d]; } /*! Multiple directions forward mode Taylor coefficients for op = MulpvOp. The C++ source code corresponding to this operation is \verbatim z = x * y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op_dir */ template inline void forward_mulpv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; size_t m = (q-1) * r + 1; Base* y = taylor + arg[1] * num_taylor_per_var + m; Base* z = taylor + i_z * num_taylor_per_var + m; // Paraemter value Base x = parameter[ arg[0] ]; for(size_t ell = 0; ell < r; ell++) z[ell] = x * y[ell]; } /*! Compute zero order forward mode Taylor coefficient for result of op = MulpvOp. The C++ source code corresponding to this operation is \verbatim z = x * y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op_0 */ template inline void forward_mulpv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 ); // Paraemter value Base x = parameter[ arg[0] ]; // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x * y[0]; } /*! Compute reverse mode partial derivative for result of op = MulpvOp. The C++ source code corresponding to this operation is \verbatim z = x * y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails reverse_binary_op */ template inline void reverse_mulpv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Arguments Base x = parameter[ arg[0] ]; // Partial derivatives corresponding to arguments and result Base* py = partial + arg[1] * nc_partial; Base* pz = partial + i_z * nc_partial; // number of indices to access size_t j = d + 1; while(j) { --j; py[j] += pz[j] * x; } } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sub_eq.hpp0000644000176200001440000000474714536067013017465 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SUB_EQ_INCLUDED # define CPPAD_SUB_EQ_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD& AD::operator -= (const AD &right) { // compute the Base part Base left; left = value_; value_ -= right.value_; // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return *this; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_left = tape_id_ == tape_id; bool var_right = right.tape_id_ == tape_id; if( var_left ) { if( var_right ) { // this = variable - variable CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(taddr_, right.taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(SubvvOp); // make this a variable CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id ); } else if( IdenticalZero( right.value_ ) ) { // this = variable - 0 } else { // this = variable - parameter CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(taddr_, p); // put operator in the tape taddr_ = tape->Rec_.PutOp(SubvpOp); // make this a variable CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id ); } } else if( var_right ) { // this = parameter - variable CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(left); tape->Rec_.PutArg(p, right.taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(SubpvOp); // make this a variable tape_id_ = tape_id; } return *this; } CPPAD_FOLD_ASSIGNMENT_OPERATOR(-=) } // END CppAD namespace # endif TMB/inst/include/cppad/local/print_op.hpp0000644000176200001440000000725414536067013020035 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_PRINT_OP_INCLUDED # define CPPAD_PRINT_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! Print operation for parameters; i.e., op = PriOp. The C++ source code corresponding to this operation is \verbatim f.Forward(0, x) PrintFor(before, var) PrintFor(pos, before, var, after) \endverbatim The PrintFor call puts the print operation on the tape and the print occurs during the zero order forward mode computation. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param s_out the results are printed on this output stream. \param arg \a arg[0] & 1 \n If this is zero, \a pos is a parameter. Otherwise it is a variable. \n \a arg[0] & 2 \n If this is zero, \a var is a parameter. Otherwise it is a variable. \n \n \a arg[1] \n If \a pos is a parameter, parameter[arg[1]] is its value. Othwise taylor[ arg[1] * cap_order + 0 ] is the zero order Taylor coefficient for \a pos. \n \n \a arg[2] \n index of the text to be printed before \a var if \a pos is not a positive value. \n \n \a arg[3] \n If \a var is a parameter, parameter[arg[3]] is its value. Othwise taylor[ arg[3] * cap_order + 0 ] is the zero order Taylor coefficient for \a var. \n \n \a arg[4] \n index of the text to be printed after \a var if \a pos is not a positive value. \param num_text is the total number of text characters on the tape (only used for error checking). \param text \b Input: text[arg[1]] is the first character of the text that will be printed. All the characters from there to (but not including) the first '\\0' are printed. \param num_par is the total number of values in the \a parameter vector \param parameter Contains the value of parameters. \param cap_order number of colums in the matrix containing all the Taylor coefficients. \param taylor Contains the value of variables. \par Checked Assertions: \li NumArg(PriOp) == 5 \li NumRes(PriOp) == 0 \li text != CPPAD_NULL \li arg[1] < num_text \li if \a pos is a parameter, arg[1] < num_par \li if \a var is a parameter, arg[3] < num_par */ template inline void forward_pri_0( std::ostream& s_out , const addr_t* arg , size_t num_text , const char* text , size_t num_par , const Base* parameter , size_t cap_order , const Base* taylor ) { Base pos, var; const char* before; const char* after; CPPAD_ASSERT_NARG_NRES(PriOp, 5, 0); // pos if( arg[0] & 1 ) { pos = taylor[ arg[1] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); pos = parameter[ arg[1] ]; } // before CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_text ); before = text + arg[2]; // var if( arg[0] & 2 ) { var = taylor[ arg[3] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); var = parameter[ arg[3] ]; } // after CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_text ); after = text + arg[4]; if( ! GreaterThanZero( pos ) ) s_out << before << var << after; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/user_ad.hpp0000644000176200001440000000373614536067013017626 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_USER_AD_INCLUDED # define CPPAD_USER_AD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- $begin AD$$ $spell std bool cos Cpp $$ $section AD Objects$$ $index AD, object$$ $head Purpose$$ The sections listed below describe the operations that are available to $cref/AD of Base/glossary/AD of Base/$$ objects. These objects are used to $cref/tape/glossary/Tape/$$ an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. This operation sequence can be transferred to an $cref ADFun$$ object where it can be used to evaluate the corresponding function and derivative values. $head Base Type Requirements$$ $index Base, require$$ The $icode Base$$ requirements are provided by the CppAD package for the following base types: $code float$$, $code double$$, $code std::complex$$, $code std::complex$$. Otherwise, see $cref base_require$$. $childtable% cppad/local/ad_ctor.hpp% cppad/local/ad_assign.hpp% cppad/local/convert.hpp% cppad/local/ad_valued.hpp% cppad/local/bool_valued.hpp% cppad/local/vec_ad.hpp% cppad/base_require.hpp %$$ $end --------------------------------------------------------------------------- */ # include # include # include # include # include # include # endif TMB/inst/include/cppad/local/reverse_sweep.hpp0000644000176200001440000011142614536067013021056 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_REVERSE_SWEEP_INCLUDED # define CPPAD_REVERSE_SWEEP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file reverse_sweep.hpp Compute derivatives of arbitrary order Taylor coefficients. */ /* \def CPPAD_ATOMIC_CALL This avoids warnings when NDEBUG is defined and user_ok is not used. If \c NDEBUG is defined, this resolves to \code user_atom->reverse \endcode otherwise, it respolves to \code user_ok = user_atom->reverse \endcode This maco is undefined at the end of this file to facillitate is use with a different definition in other files. */ # ifdef NDEBUG # define CPPAD_ATOMIC_CALL user_atom->reverse # else # define CPPAD_ATOMIC_CALL user_ok = user_atom->reverse # endif /*! \def CPPAD_REVERSE_SWEEP_TRACE This value is either zero or one. Zero is the normal operational value. If it is one, a trace of every reverse_sweep computation is printed. */ # define CPPAD_REVERSE_SWEEP_TRACE 0 /*! Compute derivative of arbitrary order forward mode Taylor coefficients. \tparam Base base type for the operator; i.e., this operation sequence was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param d is the highest order Taylor coefficients that we are computing the derivative of. \param n is the number of independent variables on the tape. \param numvar is the total number of variables on the tape. This is also equal to the number of rows in the matrix \a Taylor; i.e., play->num_var_rec(). \param play The information stored in \a play is a recording of the operations corresponding to the function \f[ F : {\bf R}^n \rightarrow {\bf R}^m \f] where \f$ n \f$ is the number of independent variables and \f$ m \f$ is the number of dependent variables. We define \f$ u^{(k)} \f$ as the value of x_k in the previous call of the form f.Forward(k, x_k) We define \f$ X : {\bf R}^{n \times d} \rightarrow {\bf R}^n \f$ by \f[ X(t, u) = u^{(0)} + u^{(1)} t + \cdots + u^{(d)} t^d \f] We define \f$ Y : {\bf R}^{n \times d} \rightarrow {\bf R}^m \f$ by \f[ Y(t, u) = F[ X(t, u) ] \f] We define the function \f$ W : {\bf R}^{n \times d} \rightarrow {\bf R} \f$ by \f[ W(u) = \sum_{k=0}^{d} ( w^{(k)} )^{\rm T} \frac{1}{k !} \frac{\partial^k}{\partial t^k} Y(0, u) \f] (The matrix \f$ w \in {\bf R}^m \f$, is defined below under the heading Partial.) Note that the scale factor 1 / k converts the k-th partial derivative to the k-th order Taylor coefficient. This routine computes the derivative of \f$ W(u) \f$ with respect to all the Taylor coefficients \f$ u^{(k)} \f$ for \f$ k = 0 , ... , d \f$. \n \n The object \a play is effectly constant. There is an exception to this, while palying back the tape the object \a play holds information about the current location with in the tape and this changes during palyback. \param J Is the number of columns in the coefficient matrix \a Taylor. This must be greater than or equal \a d + 1. \param Taylor For i = 1 , ... , \a numvar, and for k = 0 , ... , \a d, \a Taylor [ i * J + k ] is the k-th order Taylor coefficient corresponding to variable with index i on the tape. The value \f$ u \in {\bf R}^{n \times d} \f$, at which the derivative is computed, is defined by \f$ u_j^{(k)} \f$ = \a Taylor [ j * J + k ] for j = 1 , ... , \a n, and for k = 0 , ... , \a d. \param K Is the number of columns in the partial derivative matrix \a Partial. It must be greater than or equal \a d + 1. \param Partial \b Input: The last \f$ m \f$ rows of \a Partial are inputs. The matrix \f$ w \f$, used to define \f$ W(u) \f$, is specified by these rows. For i = 0 , ... , m - 1, for k = 0 , ... , d, Partial [ (numvar - m + i ) * K + k ] = w[i,k]. \n \n \b Temporary: For i = n+1 , ... , \a numvar - 1 and for k = 0 , ... , d, the value of \a Partial [ i * K + k ] is used for temporary work space and its output value is not defined. \n \n \b Output: For j = 1 , ... , n and for k = 0 , ... , d, \a Partial [ j * K + k ] is the partial derivative of \f$ W( u ) \f$ with respect to \f$ u_j^{(k)} \f$. \param cskip_op Is a vector with size play->num_op_rec(). If cskip_op[i] is true, the operator index i in the recording does not affect any of the dependent variable (given the value of the independent variables). \param var_by_load_op is a vector with size play->num_load_op_rec(). Is the variable index corresponding to each load instruction. In the case where the index is zero, the instruction corresponds to a parameter (not variable). \par Assumptions The first operator on the tape is a BeginOp, and the next \a n operators are InvOp operations for the corresponding independent variables. */ template void ReverseSweep( size_t d, size_t n, size_t numvar, player* play, size_t J, const Base* Taylor, size_t K, Base* Partial, bool* cskip_op, const pod_vector& var_by_load_op ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // work space used by UserOp. const size_t user_k = d; // highest order we are differentiating const size_t user_k1 = d+1; // number of orders for this calculation vector user_ix; // variable indices for argument vector vector user_tx; // argument vector Taylor coefficients vector user_ty; // result vector Taylor coefficients vector user_px; // partials w.r.t argument vector vector user_py; // partials w.r.t. result vector size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_end; // temporary indices size_t j, ell; // Initialize play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REVERSE_SWEEP_TRACE Rcout << std::endl; # endif bool more_operators = true; while(more_operators) { // next op play->reverse_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN((i_op > n) | (op == InvOp) | (op == BeginOp)); CPPAD_ASSERT_UNKNOWN((i_op <= n) | (op != InvOp) | (op != BeginOp)); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); // check if we are skipping this operation while( cskip_op[i_op] ) { if( op == CSumOp ) { // CSumOp has a variable number of arguments play->reverse_csum(op, arg, i_op, i_var); } CPPAD_ASSERT_UNKNOWN( op != CSkipOp ); // if( op == CSkipOp ) // { // CSkip has a variable number of arguments // play->reverse_cskip(op, arg, i_op, i_var); // } CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); play->reverse_next(op, arg, i_op, i_var); } // rest of informaiton depends on the case # if CPPAD_REVERSE_SWEEP_TRACE if( op == CSumOp ) { // CSumOp has a variable number of arguments play->reverse_csum(op, arg, i_op, i_var); } if( op == CSkipOp ) { // CSkip has a variable number of arguments play->reverse_cskip(op, arg, i_op, i_var); } size_t i_tmp = i_var; const Base* Z_tmp = Taylor + i_var * J; const Base* pZ_tmp = Partial + i_var * K; printOp( Rcout, play, i_op, i_tmp, op, arg ); if( NumRes(op) > 0 && op != BeginOp ) printOpResult( Rcout, d + 1, Z_tmp, d + 1, pZ_tmp ); Rcout << std::endl; # endif switch( op ) { case AbsOp: reverse_abs_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_acos_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AddvvOp: reverse_addvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_addpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_asin_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_atan_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); more_operators = false; break; // -------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // forward_next thinks it one has one argument. // we must inform reverse_next of this special case. # if ! CPPAD_REVERSE_SWEEP_TRACE play->reverse_cskip(op, arg, i_op, i_var); # endif break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. # if ! CPPAD_REVERSE_SWEEP_TRACE play->reverse_csum(op, arg, i_op, i_var); # endif reverse_csum_op( d, i_var, arg, K, Partial ); // end of a cummulative summation break; // ------------------------------------------------- case CExpOp: reverse_cond_op( d, i_var, arg, num_par, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case CosOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_cos_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case CoshOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_cosh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case DisOp: // Derivative of discrete operation is zero so no // contribution passes through this operation. break; // -------------------------------------------------- case DivvvOp: reverse_divvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_divpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_divvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- # if CPPAD_COMPILER_HAS_ERF case ErfOp: reverse_erf_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; # endif // -------------------------------------------------- case ExpOp: reverse_exp_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case InvOp: break; // -------------------------------------------------- case LdpOp: reverse_load_op( op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data() ); break; // ------------------------------------------------- case LdvOp: reverse_load_op( op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data() ); break; // -------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: break; // ------------------------------------------------- case LogOp: reverse_log_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case MulvvOp: reverse_mulvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_mulpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case ParOp: break; // -------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_powvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_powpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case PowvvOp: reverse_powvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case PriOp: // no result so nothing to do break; // -------------------------------------------------- case SignOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sign_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case SinOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sin_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case SinhOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sinh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case SqrtOp: reverse_sqrt_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case StppOp: break; // -------------------------------------------------- case StpvOp: break; // ------------------------------------------------- case StvpOp: break; // ------------------------------------------------- case StvvOp: break; // -------------------------------------------------- case SubvvOp: reverse_subvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_subpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_subvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case TanOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_tan_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case TanhOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_tanh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_end ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_ix.size() != user_n) user_ix.resize(user_n); if(user_tx.size() != user_n * user_k1) { user_tx.resize(user_n * user_k1); user_px.resize(user_n * user_k1); } if(user_ty.size() != user_m * user_k1) { user_ty.resize(user_m * user_k1); user_py.resize(user_m * user_k1); } user_j = user_n; user_i = user_m; user_state = user_ret; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); CPPAD_ATOMIC_CALL( user_k, user_tx, user_ty, user_px, user_py ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base.reverse: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(j = 0; j < user_n; j++) if( user_ix[j] > 0 ) { for(ell = 0; ell < user_k1; ell++) Partial[user_ix[j] * K + ell] += user_px[j * user_k1 + ell]; } user_state = user_end; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_j; user_ix[user_j] = 0; user_tx[user_j * user_k1 + 0] = parameter[ arg[0]]; for(ell = 1; ell < user_k1; ell++) user_tx[user_j * user_k1 + ell] = Base(0.); if( user_j == 0 ) user_state = user_start; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); --user_j; user_ix[user_j] = arg[0]; for(ell = 0; ell < user_k1; ell++) user_tx[user_j*user_k1 + ell] = Taylor[ arg[0] * J + ell]; if( user_j == 0 ) user_state = user_start; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_i; for(ell = 0; ell < user_k1; ell++) { user_py[user_i * user_k1 + ell] = Base(0.); user_ty[user_i * user_k1 + ell] = Base(0.); } user_ty[user_i * user_k1 + 0] = parameter[ arg[0] ]; if( user_i == 0 ) user_state = user_arg; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); --user_i; for(ell = 0; ell < user_k1; ell++) { user_py[user_i * user_k1 + ell] = Partial[i_var * K + ell]; user_ty[user_i * user_k1 + ell] = Taylor[i_var * J + ell]; } if( user_i == 0 ) user_state = user_arg; break; // ------------------------------------------------------------ default: CPPAD_ASSERT_UNKNOWN(false); } } # if CPPAD_REVERSE_SWEEP_TRACE Rcout << std::endl; # endif // values corresponding to BeginOp CPPAD_ASSERT_UNKNOWN( i_op == 0 ); CPPAD_ASSERT_UNKNOWN( i_var == 0 ); } /* =============================== Kaspers reverseSweep*/ template void myReverseSweep( size_t d, size_t n, size_t numvar, player* Rec, size_t J, const Base* Taylor, size_t K, Base* Partial, size_t dep_var_index, // <-- dependent variable to consider // vector& op_mark, // <-- operator dependency workspace // vector& var2op, // vector& tp, ADFun* pf, const pod_vector& var_by_load_op ) { // TODO: sub-sequence // Create workspace indexed by the oprator index w[i_op] such that // w[i_op]>0 means that "i_op" belongs to the relevant sub-sequence. // (We skip an operation if w[i_op]==0 by calling next_reverse.) // To begin with - after start_reverse - i_op will point to the last dependent variable. // (To start with lower index just call next_reverse a couple of times) // 1. Create Mapping from "op" to // 1. Choose dependent variable. (from myReverse) // /* Idea: Create workspace of relevant oprations. Consider a given _relevant_ operator "op". Take all argument addresses. Place their indices in the workspace vector w. Call next_reverse as long as w[i_op]=0. We then have the next relevant op - and proceed as before. Update: It seems to be easier to maintain a vector of _argument_ dependencies rather than _operator_ dependencies. */ //Rcout << "myReverseSweep" << dep_var_taddr << "\n"; //vector relevant(Rec->num_var_rec()); /* use dep_var_taddr as mark to avoid resetting workspace */ //pf->op_mark_[pf->var2op_[dep_var_taddr]]=dep_var_taddr; //Rcout << relevant << "\n"; pf->prepare_reverse_sweep(dep_var_index); std::vector::reverse_iterator it; OpCode op; # ifndef NDEBUG size_t i_op; # endif size_t i_var; const addr_t* arg = 0; // check numvar argument CPPAD_ASSERT_UNKNOWN( Rec->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // length of the parameter vector (used by CppAD assert macros) const size_t num_par = Rec->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = 0; if( num_par > 0 ) parameter = Rec->GetPar(); // work space used by UserOp. const size_t user_k = d; // order of this forward mode calculation const size_t user_k1 = d+1; // number of orders for this calculation vector user_ix; // variable indices for argument vector vector user_tx; // argument vector Taylor coefficients vector user_ty; // result vector Taylor coefficients vector user_px; // partials w.r.t argument vector vector user_py; // partials w.r.t. result vector size_t user_index = 0; // indentifier for this user_atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_end; // temporary indices size_t j, ell; // Initialize // Rec->start_reverse(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REVERSE_SWEEP_TRACE Rcout << std::endl; # endif //while(op != BeginOp ) for(it=pf->op_mark_index_.rbegin();it!=pf->op_mark_index_.rend();it++) { // next op // pf->my_next_reverse(op, arg, i_op, i_var, // dep_var_taddr); op = pf->tp_[*it].op; arg = pf->tp_[*it].op_arg; # ifndef NDEBUG i_op = pf->tp_[*it].op_index; # endif i_var = pf->tp_[*it].var_index; # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // rest of informaiton depends on the case # if CPPAD_REVERSE_SWEEP_TRACE size_t i_tmp = i_var; const Base* Z_tmp = Taylor + i_var * J; const Base* pZ_tmp = Partial + i_var * K; printOp( Rcout, Rec, i_tmp, op, arg, d + 1, Z_tmp, d + 1, pZ_tmp ); # endif switch( op ) { case AbsOp: reverse_abs_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AddvvOp: reverse_addvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_addpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_acos_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_asin_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_atan_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // -------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // next_reverse thinks it one has one argument. // We must inform next_reverse of this special case. /* HOWEVER for myReverse all pointers are precomputed... */ /* Rec->reverse_csum(op, arg, i_op, i_var); */ reverse_csum_op( d, i_var, arg, K, Partial ); // end of a cummulative summation break; // ------------------------------------------------- case CExpOp: reverse_cond_op( d, i_var, arg, num_par, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: break; // -------------------------------------------------- case CosOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_cos_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case CoshOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_cosh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case DisOp: // Derivative of discrete operation is zero so no // contribution passes through this operation. break; // -------------------------------------------------- case DivvvOp: reverse_divvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_divpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_divvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- # if CPPAD_COMPILER_HAS_ERF case ErfOp: reverse_erf_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; # endif // -------------------------------------------------- case ExpOp: reverse_exp_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case LdpOp: reverse_load_op( op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data() ); break; // ------------------------------------------------- case LdvOp: reverse_load_op( op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data() ); break; // ------------------------------------------------- case InvOp: break; // -------------------------------------------------- case LogOp: reverse_log_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case MulvvOp: reverse_mulvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_mulpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case ParOp: break; // -------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_powvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_powpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case PowvvOp: reverse_powvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case PriOp: // no result so nothing to do break; // -------------------------------------------------- case SignOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sign_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case SinOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sin_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case SinhOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sinh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case SqrtOp: reverse_sqrt_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case StppOp: break; // -------------------------------------------------- case StpvOp: break; // ------------------------------------------------- case StvpOp: break; // ------------------------------------------------- case StvvOp: break; // -------------------------------------------------- case SubvvOp: reverse_subvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_subpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_subvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case TanOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_tan_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case TanhOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_tanh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_end ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_ix.size() != user_n) user_ix.resize(user_n); if(user_tx.size() != user_n * user_k1) { user_tx.resize(user_n * user_k1); user_px.resize(user_n * user_k1); } if(user_ty.size() != user_m * user_k1) { user_ty.resize(user_m * user_k1); user_py.resize(user_m * user_k1); } user_j = user_n; user_i = user_m; user_state = user_ret; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); CPPAD_ATOMIC_CALL( user_k, user_tx, user_ty, user_px, user_py ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base.reverse: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(j = 0; j < user_n; j++) if( user_ix[j] > 0 ) { for(ell = 0; ell < user_k1; ell++) Partial[user_ix[j] * K + ell] += user_px[j * user_k1 + ell]; } user_state = user_end; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_j; user_ix[user_j] = 0; user_tx[user_j * user_k1 + 0] = parameter[ arg[0]]; for(ell = 1; ell < user_k1; ell++) user_tx[user_j * user_k1 + ell] = Base(0.); if( user_j == 0 ) user_state = user_start; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); --user_j; user_ix[user_j] = arg[0]; for(ell = 0; ell < user_k1; ell++) user_tx[user_j*user_k1 + ell] = Taylor[ arg[0] * J + ell]; if( user_j == 0 ) user_state = user_start; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_i; for(ell = 0; ell < user_k1; ell++) { user_py[user_i * user_k1 + ell] = Base(0.); user_ty[user_i * user_k1 + ell] = Base(0.); } user_ty[user_i * user_k1 + 0] = parameter[ arg[0] ]; if( user_i == 0 ) user_state = user_arg; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); --user_i; for(ell = 0; ell < user_k1; ell++) { user_py[user_i * user_k1 + ell] = Partial[i_var * K + ell]; user_ty[user_i * user_k1 + ell] = Taylor[i_var * J + ell]; } if( user_i == 0 ) user_state = user_arg; break; // ------------------------------------------------------------ default: CPPAD_ASSERT_UNKNOWN(false); } } # if CPPAD_REVERSE_SWEEP_TRACE Rcout << std::endl; # endif // values corresponding to BeginOp CPPAD_ASSERT_UNKNOWN( i_op == 0 ); CPPAD_ASSERT_UNKNOWN( i_var == 0 ); } /* =============================== End kaspers reverseSweep */ } // END_CPPAD_NAMESPACE // preprocessor symbols that are local to this file # undef CPPAD_REVERSE_SWEEP_TRACE # undef CPPAD_ATOMIC_CALL # endif TMB/inst/include/cppad/local/lu_ratio.hpp0000644000176200001440000002501314536067013020012 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_LU_RATIO_INCLUDED # define CPPAD_LU_RATIO_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin LuRatio$$ $spell cppad.hpp xk Cpp Lu bool const ip jp std ADvector $$ $index LuRatio$$ $index linear, Lu factor equation$$ $index equation, Lu factor$$ $index determinant, Lu factor$$ $index solve, Lu factor$$ $section LU Factorization of A Square Matrix and Stability Calculation$$ $head Syntax$$ $code# include $$ $pre $$ $icode%sign% = LuRatio(%ip%, %jp%, %LU%, %ratio%)%$$ $head Description$$ Computes an LU factorization of the matrix $icode A$$ where $icode A$$ is a square matrix. A measure of the numerical stability called $icode ratio$$ is calculated. This ratio is useful when the results of $code LuRatio$$ are used as part of an $cref ADFun$$ object. $head Include$$ This routine is designed to be used with AD objects and requires the $code cppad/cppad.hpp$$ file to be included. $head Matrix Storage$$ All matrices are stored in row major order. To be specific, if $latex Y$$ is a vector that contains a $latex p$$ by $latex q$$ matrix, the size of $latex Y$$ must be equal to $latex p * q $$ and for $latex i = 0 , \ldots , p-1$$, $latex j = 0 , \ldots , q-1$$, $latex \[ Y_{i,j} = Y[ i * q + j ] \] $$ $head sign$$ The return value $icode sign$$ has prototype $codei% int %sign% %$$ If $icode A$$ is invertible, $icode sign$$ is plus or minus one and is the sign of the permutation corresponding to the row ordering $icode ip$$ and column ordering $icode jp$$. If $icode A$$ is not invertible, $icode sign$$ is zero. $head ip$$ The argument $icode ip$$ has prototype $codei% %SizeVector% &%ip% %$$ (see description of $cref/SizeVector/LuFactor/SizeVector/$$ below). The size of $icode ip$$ is referred to as $icode n$$ in the specifications below. The input value of the elements of $icode ip$$ does not matter. The output value of the elements of $icode ip$$ determine the order of the rows in the permuted matrix. $head jp$$ The argument $icode jp$$ has prototype $codei% %SizeVector% &%jp% %$$ (see description of $cref/SizeVector/LuFactor/SizeVector/$$ below). The size of $icode jp$$ must be equal to $icode n$$. The input value of the elements of $icode jp$$ does not matter. The output value of the elements of $icode jp$$ determine the order of the columns in the permuted matrix. $head LU$$ The argument $icode LU$$ has the prototype $codei% %ADvector% &%LU% %$$ and the size of $icode LU$$ must equal $latex n * n$$ (see description of $cref/ADvector/LuRatio/ADvector/$$ below). $subhead A$$ We define $icode A$$ as the matrix corresponding to the input value of $icode LU$$. $subhead P$$ We define the permuted matrix $icode P$$ in terms of $icode A$$ by $codei% %P%(%i%, %j%) = %A%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ $subhead L$$ We define the lower triangular matrix $icode L$$ in terms of the output value of $icode LU$$. The matrix $icode L$$ is zero above the diagonal and the rest of the elements are defined by $codei% %L%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ for $latex i = 0 , \ldots , n-1$$ and $latex j = 0 , \ldots , i$$. $subhead U$$ We define the upper triangular matrix $icode U$$ in terms of the output value of $icode LU$$. The matrix $icode U$$ is zero below the diagonal, one on the diagonal, and the rest of the elements are defined by $codei% %U%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ for $latex i = 0 , \ldots , n-2$$ and $latex j = i+1 , \ldots , n-1$$. $subhead Factor$$ If the return value $icode sign$$ is non-zero, $codei% %L% * %U% = %P% %$$ If the return value of $icode sign$$ is zero, the contents of $icode L$$ and $icode U$$ are not defined. $subhead Determinant$$ $index determinant$$ If the return value $icode sign$$ is zero, the determinant of $icode A$$ is zero. If $icode sign$$ is non-zero, using the output value of $icode LU$$ the determinant of the matrix $icode A$$ is equal to $codei% %sign% * %LU%[%ip%[0], %jp%[0]] * %...% * %LU%[%ip%[%n%-1], %jp%[%n%-1]] %$$ $head ratio$$ The argument $icode ratio$$ has prototype $codei% AD<%Base%> &%ratio% %$$ On input, the value of $icode ratio$$ does not matter. On output it is a measure of how good the choice of pivots is. For $latex p = 0 , \ldots , n-1$$, the $th p$$ pivot element is the element of maximum absolute value of a $latex (n-p) \times (n-p)$$ sub-matrix. The ratio of each element of sub-matrix divided by the pivot element is computed. The return value of $icode ratio$$ is the maximum absolute value of such ratios over with respect to all elements and all the pivots. $subhead Purpose$$ Suppose that the execution of a call to $code LuRatio$$ is recorded in the $codei%ADFun<%Base%>%$$ object $icode F$$. Then a call to $cref Forward$$ of the form $codei% %F%.Forward(%k%, %xk%) %$$ with $icode k$$ equal to zero will revaluate this Lu factorization with the same pivots and a new value for $icode A$$. In this case, the resulting $icode ratio$$ may not be one. If $icode ratio$$ is too large (the meaning of too large is up to you), the current pivots do not yield a stable LU factorization of $icode A$$. A better choice for the pivots (for this value of $icode A$$) will be made if you recreate the $code ADFun$$ object starting with the $cref Independent$$ variable values that correspond to the vector $icode xk$$. $head SizeVector$$ The type $icode SizeVector$$ must be a $cref SimpleVector$$ class with $cref/elements of type size_t/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head ADvector$$ The type $icode ADvector$$ must be a $cref/simple vector class/SimpleVector/$$ with elements of type $codei%AD<%Base%>%$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Example$$ $children% example/lu_ratio.cpp %$$ The file $cref lu_ratio.cpp$$ contains an example and test of using $code LuRatio$$. It returns true if it succeeds and false otherwise. $end -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN CppAD namespace // Lines different from the code in cppad/lu_factor.hpp end with // template // int LuRatio(SizeVector &ip, SizeVector &jp, ADvector &LU, AD &ratio) // { typedef ADvector FloatVector; // typedef AD Float; // // check numeric type specifications CheckNumericType(); // check simple vector class specifications CheckSimpleVector(); CheckSimpleVector(); size_t i, j; // some temporary indices const Float zero( 0 ); // the value zero as a Float object size_t imax; // row index of maximum element size_t jmax; // column indx of maximum element Float emax; // maximum absolute value size_t p; // count pivots int sign; // sign of the permutation Float etmp; // temporary element Float pivot; // pivot element // ------------------------------------------------------- size_t n = size_t(ip.size()); CPPAD_ASSERT_KNOWN( size_t(jp.size()) == n, "Error in LuFactor: jp must have size equal to n" ); CPPAD_ASSERT_KNOWN( size_t(LU.size()) == n * n, "Error in LuFactor: LU must have size equal to n * m" ); // ------------------------------------------------------- // initialize row and column order in matrix not yet pivoted for(i = 0; i < n; i++) { ip[i] = i; jp[i] = i; } // initialize the sign of the permutation sign = 1; // initialize the ratio // ratio = Float(1); // // --------------------------------------------------------- // Reduce the matrix P to L * U using n pivots for(p = 0; p < n; p++) { // determine row and column corresponding to element of // maximum absolute value in remaining part of P imax = jmax = n; emax = zero; for(i = p; i < n; i++) { for(j = p; j < n; j++) { CPPAD_ASSERT_UNKNOWN( (ip[i] < n) & (jp[j] < n) ); etmp = LU[ ip[i] * n + jp[j] ]; // check if maximum absolute value so far if( AbsGeq (etmp, emax) ) { imax = i; jmax = j; emax = etmp; } } } for(i = p; i < n; i++) // { for(j = p; j < n; j++) // { etmp = abs(LU[ ip[i] * n + jp[j] ] / emax); // ratio = // CondExpGt(etmp, ratio, etmp, ratio); // } // } // CPPAD_ASSERT_KNOWN( (imax < n) & (jmax < n) , "AbsGeq must return true when second argument is zero" ); if( imax != p ) { // switch rows so max absolute element is in row p i = ip[p]; ip[p] = ip[imax]; ip[imax] = i; sign = -sign; } if( jmax != p ) { // switch columns so max absolute element is in column p j = jp[p]; jp[p] = jp[jmax]; jp[jmax] = j; sign = -sign; } // pivot using the max absolute element pivot = LU[ ip[p] * n + jp[p] ]; // check for determinant equal to zero if( pivot == zero ) { // abort the mission return 0; } // Reduce U by the elementary transformations that maps // LU( ip[p], jp[p] ) to one. Only need transform elements // above the diagonal in U and LU( ip[p] , jp[p] ) is // corresponding value below diagonal in L. for(j = p+1; j < n; j++) LU[ ip[p] * n + jp[j] ] /= pivot; // Reduce U by the elementary transformations that maps // LU( ip[i], jp[p] ) to zero. Only need transform elements // above the diagonal in U and LU( ip[i], jp[p] ) is // corresponding value below diagonal in L. for(i = p+1; i < n; i++ ) { etmp = LU[ ip[i] * n + jp[p] ]; for(j = p+1; j < n; j++) { LU[ ip[i] * n + jp[j] ] -= etmp * LU[ ip[p] * n + jp[j] ]; } } } return sign; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/parameter_op.hpp0000644000176200001440000000473714536067013020664 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_PARAMETER_OP_INCLUDED # define CPPAD_PARAMETER_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file parameter_op.hpp Zero order forward mode for ParOp */ /*! Compute zero order forward mode Taylor coefficient for result of op = ParOp. The C++ source code corresponding to this operation is one of the following \verbatim ADFun f(x, y) f.Dependent(x, y) \endverbatim where some of the components of the vector y are parameters. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to the component of y that is a parameter. \param arg \a arg[0] \n index corresponding to the parameter value for this operator. \param num_par is the number of parameters in \a parameter. \param parameter \b Input: \a parameter[ \a arg[0] ] is the value of a component of y that is a parameter. \param cap_order number of colums in the matrix containing all the Taylor coefficients. \param taylor \b Output: \a taylor [ \a i_z * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to z. \par Checked Assertions where op is the unary operator with one result: \li NumArg(op) == 1 \li NumRes(op) == 1 \li \a size_t(arg[0]) < num_par \li \a 0 < \a cap_order */ template inline void forward_par_op_0( size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(ParOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); Base* z = taylor + i_z * cap_order; z[0] = parameter[ arg[0] ]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/exp_op.hpp0000644000176200001440000001123114536067013017463 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_EXP_OP_INCLUDED # define CPPAD_EXP_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file exp_op.hpp Forward and reverse mode calculations for z = exp(x). */ /*! Forward mode Taylor coefficient for result of op = ExpOp. The C++ source code corresponding to this operation is \verbatim z = exp(x) \endverbatim \copydetails forward_unary1_op */ template inline void forward_exp_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; size_t k; if( p == 0 ) { z[0] = exp( x[0] ); p++; } for(size_t j = p; j <= q; j++) { z[j] = x[1] * z[j-1]; for(k = 2; k <= j; k++) z[j] += Base(k) * x[k] * z[j-k]; z[j] /= Base(j); } } /*! Multiple direction forward mode Taylor coefficient for op = ExpOp. The C++ source code corresponding to this operation is \verbatim z = exp(x) \endverbatim \copydetails forward_unary1_op_dir */ template inline void forward_exp_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( 0 < q ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; size_t m = (q-1)*r + 1; for(size_t ell = 0; ell < r; ell++) { z[m+ell] = Base(q) * x[m+ell] * z[0]; for(size_t k = 1; k < q; k++) z[m+ell] += Base(k) * x[(k-1)*r+ell+1] * z[(q-k-1)*r+ell+1]; z[m+ell] /= Base(q); } } /*! Zero order forward mode Taylor coefficient for result of op = ExpOp. The C++ source code corresponding to this operation is \verbatim z = exp(x) \endverbatim \copydetails forward_unary1_op_0 */ template inline void forward_exp_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; z[0] = exp( x[0] ); } /*! Reverse mode partial derivatives for result of op = ExpOp. The C++ source code corresponding to this operation is \verbatim z = exp(x) \endverbatim \copydetails reverse_unary1_op */ template inline void reverse_exp_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to result const Base* z = taylor + i_z * cap_order; Base* pz = partial + i_z * nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; // loop through orders in reverse size_t j, k; j = d; while(j) { // scale partial w.r.t z[j] pz[j] /= Base(j); for(k = 1; k <= j; k++) { px[k] += pz[j] * Base(k) * z[j-k]; pz[j-k] += pz[j] * Base(k) * x[k]; } --j; } px[0] += pz[0] * z[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/cppad_colpack.cpp0000644000176200001440000001435714113627761020766 0ustar liggesusers/* $Id$ */ /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file cppad_colpack.cpp The CppAD interface to the Colpack coloring algorithms. */ /*! Determine which rows of a general sparse matrix can be computed together. \param color is a vector with color.size() == m. For i = 0 , ... , m-1, color[i] is the color for the corresponding row of the matrix. If color[i1]==color[i2], (i1, j1) is in sparsity pattern, and (i2, j2) is in sparsity pattern, then j1 is not equal to j2. \param m is the number of rows in the matrix. \param n is the number of columns in the matrix. \param adolc_pattern is a vector with adolc_pattern.size() == m. For i = 0 , ... , m-1, and for k = 1, ... ,adolc_pattern[i][0], the entry with index (i, adolc_pattern[i][k]) is a non-zero in the sparsity pattern for the matrix. */ // ---------------------------------------------------------------------- void cppad_colpack_general( CppAD::vector& color , size_t m , size_t n , const CppAD::vector& adolc_pattern ) { size_t i, k; CPPAD_ASSERT_UNKNOWN( adolc_pattern.size() == m ); CPPAD_ASSERT_UNKNOWN( color.size() == m ); // Use adolc sparsity pattern to create corresponding bipartite graph ColPack::BipartiteGraphPartialColoringInterface graph( SRC_MEM_ADOLC, adolc_pattern.data(), m, n ); // row ordered Partial-Distance-Two-Coloring of the bipartite graph graph.PartialDistanceTwoColoring( "SMALLEST_LAST", "ROW_PARTIAL_DISTANCE_TWO" ); // Use coloring information to create seed matrix int n_seed_row; int n_seed_col; double** seed_matrix = graph.GetSeedMatrix(&n_seed_row, &n_seed_col); CPPAD_ASSERT_UNKNOWN( size_t(n_seed_col) == m ); // now return coloring in format required by CppAD for(i = 0; i < m; i++) color[i] = m; for(k = 0; k < size_t(n_seed_row); k++) { for(i = 0; i < m; i++) { if( seed_matrix[k][i] != 0.0 ) { // check that no row appears twice in the coloring CPPAD_ASSERT_UNKNOWN( color[i] == m ); color[i] = k; } } } # ifndef NDEBUG // check that all non-zero rows appear in the coloring for(i = 0; i < m; i++) CPPAD_ASSERT_UNKNOWN(color[i] < m || adolc_pattern[i][0] == 0); // check that no rows with the same color have overlapping entries CppAD::vector found(n); for(k = 0; k < size_t(n_seed_row); k++) { size_t j, ell; for(j = 0; j < n; j++) found[j] = false; for(i = 0; i < m; i++) if( color[i] == k ) { for(ell = 0; ell < adolc_pattern[i][0]; ell++) { j = adolc_pattern[i][1 + ell]; CPPAD_ASSERT_UNKNOWN( ! found[j] ); found[j] = true; } } } # endif return; } // ---------------------------------------------------------------------- /*! Determine which rows of a symmetrix sparse matrix can be computed together. \param color is a vector with color.size() == m. For i = 0 , ... , m-1, color[i] is the color for the corresponding row of the matrix. We say that a sparsity pattern entry (i, j) is valid if for all i1, such that i1 != i and color[i1]==color[i], and all j1, such that (i1, j1) is in sparsity pattern, j1 != j. The coloring is chosen so that for all (i, j) in the sparsity pattern; either (i, j) or (j, i) is valid (possibly both). \param m is the number of rows (and columns) in the matrix. \param adolc_pattern is a vector with adolc_pattern.size() == m. For i = 0 , ... , m-1, and for k = 1, ... ,adolc_pattern[i][0], the entry with index (i, adolc_pattern[i][k]) is in the sparsity pattern for the symmetric matrix. */ void cppad_colpack_symmetric( CppAD::vector& color , size_t m , const CppAD::vector& adolc_pattern ) { size_t i; CPPAD_ASSERT_UNKNOWN( adolc_pattern.size() == m ); CPPAD_ASSERT_UNKNOWN( color.size() == m ); // Use adolc sparsity pattern to create corresponding bipartite graph ColPack::GraphColoringInterface graph( SRC_MEM_ADOLC, adolc_pattern.data(), m ); // Use STAR coloring because it has a direct recovery scheme; i.e., // not necessary to solve equations to extract values. graph.Coloring("SMALLEST_LAST", "STAR"); // Use coloring information to create seed matrix int n_seed_row; int n_seed_col; double** seed_matrix = graph.GetSeedMatrix(&n_seed_row, &n_seed_col); CPPAD_ASSERT_UNKNOWN( size_t(n_seed_row) == m ); // now return coloring for each row in format required by CppAD for(i = 0; i < m; i++) color[i] = m; for(i = 0; i < m; i++) { for(size_t k = 0; k < size_t(n_seed_col); k++) { if( seed_matrix[i][k] != 0.0 ) { CPPAD_ASSERT_UNKNOWN( color[i] == m ); color[i] = k; } } } # ifndef NDEBUG // check that every entry in the symetric matrix can be direclty recovered size_t i1, i2, j1, j2, k1, k2, nz1, nz2; for(i1 = 0; i1 < m; i1++) { nz1 = size_t(adolc_pattern[i1][0]); for(k1 = 1; k1 <= nz1; k1++) { j1 = adolc_pattern[i1][k1]; // check of a forward on color[i1] followed by a reverse // can recover entry (i1, j1) bool color_i1_ok = true; for(i2 = 0; i2 < m; i2++) if( i1 != i2 && color[i1] == color[i2] ) { nz2 = adolc_pattern[i2][0]; for(k2 = 1; k2 <= nz2; k2++) { j2 = adolc_pattern[i2][k2]; color_i1_ok &= (j1 != j2); } } // check of a forward on color[j1] followed by a reverse // can recover entry (j1, i1) bool color_j1_ok = true; for(j2 = 0; j2 < m; j2++) if( j1 != j2 && color[j1] == color[j2] ) { nz2 = adolc_pattern[j2][0]; for(k2 = 1; k2 <= nz2; k2++) { i2 = adolc_pattern[j2][k2]; color_j1_ok &= (i1 != i2); } } CPPAD_ASSERT_UNKNOWN( color_i1_ok || color_j1_ok ); } } # endif return; } } // END_CPPAD_NAMESPACE TMB/inst/include/cppad/local/cppad_colpack.hpp0000644000176200001440000000664414536067013020770 0ustar liggesusers/* $Id$ */ /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # ifndef CPPAD_CPPAD_COLPACK_INCLUDED # define CPPAD_CPPAD_COLPACK_INCLUDED # if CPPAD_HAS_COLPACK namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file cppad_colpack.hpp External interface to Colpack routines used by cppad. */ // --------------------------------------------------------------------------- /*! Link from CppAD to ColPack used for general sparse matrices. This CppAD library routine is necessary because ColPack/ColPackHeaders.h has a using namespace std at the global level. \param m [in] is the number of rows in the sparse matrix \param n [in] is the nubmer of columns in the sparse matrix. \param adolc_pattern [in] This vector has size \c m, adolc_pattern[i][0] is the number of non-zeros in row \c i. For j = 1 , ... , adolc_sparsity[i], adolc_pattern[i][j] is the column index (base zero) for the non-zeros in row \c i. \param color [out] is a vector with size \c m. The input value of its elements does not matter. Upon return, it is a coloring for the rows of the sparse matrix. \n \n If for some \c i, color[i] == m, then adolc_pattern[i][0] == 0. Otherwise, color[i] < m. \n \n Suppose two differen rows, i != r have the same color. It follows that for all column indices \c j; it is not the case that both (i, j) and (r, j) appear in the sparsity pattern. \n \n This routine tries to minimize, with respect to the choice of colors, the number of colors. */ extern void cppad_colpack_general( CppAD::vector& color , size_t m , size_t n , const CppAD::vector& adolc_pattern ); /*! Link from CppAD to ColPack used for symmetric sparse matrices (not yet used or tested). This CppAD library routine is necessary because ColPack/ColPackHeaders.h has a using namespace std at the global level. \param n [in] is the nubmer of rows and columns in the symmetric sparse matrix. \param adolc_pattern [in] This vector has size \c n, adolc_pattern[i][0] is the number of non-zeros in row \c i. For j = 1 , ... , adolc_sparsity[i], adolc_pattern[i][j] is the column index (base zero) for the non-zeros in row \c i. \param color [out] The input value of its elements does not matter. Upon return, it is a coloring for the rows of the sparse matrix. The properties of this coloring have not yet been determined; see Efficient Computation of Sparse Hessians Using Coloring and Automatic Differentiation (pdf/ad/gebemedhin14.pdf) */ extern void cppad_colpack_symmetric( CppAD::vector& color , size_t n , const CppAD::vector& adolc_pattern ); } // END_CPPAD_NAMESPACE # endif # endif TMB/inst/include/cppad/local/abs_op.hpp0000644000176200001440000000774414536067013017452 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ABS_OP_INCLUDED # define CPPAD_ABS_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file abs_op.hpp Forward and reverse mode calculations for z = abs(x). */ /*! Compute forward mode Taylor coefficient for result of op = AbsOp. The C++ source code corresponding to this operation is \verbatim z = abs(x) \endverbatim \copydetails forward_unary1_op */ template inline void forward_abs_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; for(size_t j = p; j <= q; j++) z[j] = sign(x[0]) * x[j]; } /*! Multiple directions forward mode Taylor coefficient for op = AbsOp. The C++ source code corresponding to this operation is \verbatim z = abs(x) \endverbatim \copydetails forward_unary1_op_dir */ template inline void forward_abs_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) z[m + ell] = sign(x[0]) * x[m + ell]; } /*! Compute zero order forward mode Taylor coefficient for result of op = AbsOp. The C++ source code corresponding to this operation is \verbatim z = abs(x) \endverbatim \copydetails forward_unary1_op_0 */ template inline void forward_abs_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base x0 = *(taylor + i_x * cap_order); Base* z = taylor + i_z * cap_order; z[0] = abs(x0); } /*! Compute reverse mode partial derivatives for result of op = AbsOp. The C++ source code corresponding to this operation is \verbatim z = abs(x) \endverbatim \copydetails reverse_unary1_op */ template inline void reverse_abs_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { size_t j; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to result Base* pz = partial + i_z * nc_partial; for(j = 0; j <= d; j++) px[j] += sign(x[0]) * pz[j]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/reverse.hpp0000644000176200001440000002335714536067013017660 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_REVERSE_INCLUDED # define CPPAD_REVERSE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file reverse.hpp Compute derivatives using reverse mode. */ /*! Use reverse mode to compute derivative of forward mode Taylor coefficients. The function \f$ X : {\rm R} \times {\rm R}^{n \times q} \rightarrow {\rm R} \f$ is defined by \f[ X(t , u) = \sum_{k=0}^{q-1} u^{(k)} t^k \f] The function \f$ Y : {\rm R} \times {\rm R}^{n \times q} \rightarrow {\rm R} \f$ is defined by \f[ Y(t , u) = F[ X(t, u) ] \f] The function \f$ W : {\rm R}^{n \times q} \rightarrow {\rm R} \f$ is defined by \f[ W(u) = \sum_{k=0}^{q-1} ( w^{(k)} )^{\rm T} \frac{1}{k !} \frac{ \partial^k } { t^k } Y(0, u) \f] \tparam Base base type for the operator; i.e., this operation sequence was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \tparam VectorBase is a Simple Vector class with elements of type \a Base. \param q is the number of the number of Taylor coefficients that are being differentiated (per variable). \param w is the weighting for each of the Taylor coefficients corresponding to dependent variables. If the argument \a w has size m * q , for \f$ k = 0 , \ldots , q-1 \f$ and \f$ i = 0, \ldots , m-1 \f$, \f[ w_i^{(k)} = w [ i * q + k ] \f] If the argument \a w has size \c m , for \f$ k = 0 , \ldots , q-1 \f$ and \f$ i = 0, \ldots , m-1 \f$, \f[ w_i^{(k)} = \left\{ \begin{array}{ll} w [ i ] & {\rm if} \; k = q-1 \\ 0 & {\rm otherwise} \end{array} \right. \f] \return Is a vector \f$ dw \f$ such that for \f$ j = 0 , \ldots , n-1 \f$ and \f$ k = 0 , \ldots , q-1 \f$ \f[ dw[ j * q + k ] = W^{(1)} ( x )_{j,k} \f] where the matrix \f$ x \f$ is the value for \f$ u \f$ that corresponding to the forward mode Taylor coefficients for the independent variables as specified by previous calls to Forward. */ template template VectorBase ADFun::Reverse(size_t q, const VectorBase &w) { // constants const Base zero(0); // temporary indices size_t i, j, k; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables size_t m = dep_taddr_.size(); pod_vector Partial; Partial.extend(num_var_tape_ * q); // update maximum memory requirement // memoryMax = std::max( memoryMax, // Memory() + num_var_tape_ * q * sizeof(Base) // ); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( size_t(w.size()) == m || size_t(w.size()) == (m * q), "Argument w to Reverse does not have length equal to\n" "the dimension of the range for the corresponding ADFun." ); CPPAD_ASSERT_KNOWN( q > 0, "The first argument to Reverse must be greater than zero." ); CPPAD_ASSERT_KNOWN( num_order_taylor_ >= q, "Less that q taylor_ coefficients are currently stored" " in this ADFun object." ); // special case where multiple forward directions have been computed, // but we are only using the one direction zero order results if( (q == 1) & (num_direction_taylor_ > 1) ) { num_order_taylor_ = 1; // number of orders to copy size_t c = cap_order_taylor_; // keep the same capacity setting size_t r = 1; // only keep one direction capacity_order(c, r); } CPPAD_ASSERT_KNOWN( num_direction_taylor_ == 1, "Reverse mode for Forward(q, r, xq) with more than one direction" "\n(r > 1) is not yet supported for q > 1." ); // initialize entire Partial matrix to zero for(i = 0; i < num_var_tape_; i++) for(j = 0; j < q; j++) Partial[i * q + j] = zero; // set the dependent variable direction // (use += because two dependent variables can point to same location) for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); if( size_t(w.size()) == m ) Partial[dep_taddr_[i] * q + q - 1] += w[i]; else { for(k = 0; k < q; k++) // ? should use += here, first make test to demonstrate bug Partial[ dep_taddr_[i] * q + k ] = w[i * q + k ]; } } // evaluate the derivatives CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() ); CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() ); ReverseSweep( q - 1, n, num_var_tape_, &play_, cap_order_taylor_, taylor_.data(), q, Partial.data(), cskip_op_.data(), load_op_ ); // return the derivative values VectorBase value(n * q); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ ); // independent variable taddr equals its operator taddr CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); // by the Reverse Identity Theorem // partial of y^{(k)} w.r.t. u^{(0)} is equal to // partial of y^{(q-1)} w.r.t. u^{(q - 1 - k)} if( size_t(w.size()) == m ) { for(k = 0; k < q; k++) value[j * q + k ] = Partial[ind_taddr_[j] * q + q - 1 - k]; } else { for(k = 0; k < q; k++) value[j * q + k ] = Partial[ind_taddr_[j] * q + k]; } } CPPAD_ASSERT_KNOWN( ! ( hasnan(value) && check_for_nan_ ) , "dw = f.Reverse(q, w): has a nan,\n" "but none of its Taylor coefficents are nan." ); return value; } /* =========================== kaspers Reverse */ template template //VectorBase ADFun::myReverse(size_t p, const VectorBase &w, size_t dep_var_index, VectorBase &value) void ADFun::myReverse(size_t p, const VectorBase &w, size_t dep_var_index, VectorBase &value) { CPPAD_ASSERT_KNOWN( p == 1, "myReverse only works for first order calculations." ); // constants const Base zero(0); // temporary indices size_t j, k; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables // size_t m = dep_taddr_.size(); if(false){ pod_vector Partial; Partial.extend(num_var_tape_ * p); } // update maximum memory requirement // memoryMax = std::max( memoryMax, // Memory() + num_var_tape_ * p * sizeof(Base) // ); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( w.size() == m || w.size() == (m * p), "Argument w to Reverse does not have length equal to\n" "the dimension of the range for the corresponding ADFun." ); CPPAD_ASSERT_KNOWN( p > 0, "The first argument to Reverse must be greater than zero." ); CPPAD_ASSERT_KNOWN( taylor_per_var_ >= p, "Less that p taylor_ coefficients are currently stored" " in this ADFun object." ); /* // initialize entire Partial matrix to zero for(i = 0; i < num_var_tape_; i++) for(j = 0; j < p; j++) Partial[i * p + j] = zero; // set the dependent variable direction // (use += because two dependent variables can point to same location) for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); if( w.size() == m ) Partial[dep_taddr_[i] * p + p - 1] += w[i]; else { for(k = 0; k < p; k++) // ? should use += here, first make test to demonstrate bug Partial[ dep_taddr_[i] * p + k ] = w[i * p + k ]; } } */ size_t dep_var_taddr=dep_taddr_[dep_var_index]; Partial[dep_var_taddr * p + p - 1] = 1.0; // evaluate the derivatives // vector relevant(play_.num_rec_var()); myReverseSweep( p - 1, n, num_var_tape_, &play_, cap_order_taylor_, taylor_.data(), p, Partial.data(), //dep_var_taddr, dep_var_index, // op_mark_, // var2op_, // tp_, this, load_op_ ); // return the derivative values // VectorBase value(n * p); std::vector::iterator it; for(it=op_mark_index_.begin();*it<=n;it++){ //colpattern[col][j]=*it-1; j=*it-1; for(k = 0; k < p; k++) value[j * p + k ] = Partial[ind_taddr_[j] * p + p - 1 - k]; } if(false){ for(j = 0; j < n; j++){ //if(relevant_[ ind_taddr_[j] ]==dep_var_taddr) if(op_mark_[ var2op_[ ind_taddr_[j] ] ]==dep_var_taddr) { for(k = 0; k < p; k++) value[j * p + k ] = Partial[ind_taddr_[j] * p + p - 1 - k]; } } } // Fill used Partials with zeros tape_point tp; for(it=op_mark_index_.begin();it!=op_mark_index_.end();it++){ tp=tp_[*it]; for(size_t i=0;i0){ Rcout << "Partials not correctly cleared. Nonzeros: " << countnnz << "\n"; } #endif // EXPERIMENT /* for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ ); // independent variable taddr equals its operator taddr CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); // by the Reverse Identity Theorem // partial of y^{(k)} w.r.t. u^{(0)} is equal to // partial of y^{(p-1)} w.r.t. u^{(p - 1 - k)} if( w.size() == m ) { for(k = 0; k < p; k++) value[j * p + k ] = Partial[ind_taddr_[j] * p + p - 1 - k]; } else { for(k = 0; k < p; k++) value[j * p + k ] = Partial[ind_taddr_[j] * p + k]; } } */ //return value; } /* =================== End kaspers Reverse */ } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sub_op.hpp0000644000176200001440000003165714536067013017476 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SUB_OP_INCLUDED # define CPPAD_SUB_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sub_op.hpp Forward and reverse mode calculations for z = x - y. */ // --------------------------- Subvv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = SubvvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op */ template inline void forward_subvv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; for(size_t d = p; d <= q; d++) z[d] = x[d] - y[d]; } /*! Multiple directions forward mode Taylor coefficients for op = SubvvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op_dir */ template inline void forward_subvv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; size_t m = (q-1) * r + 1; Base* x = taylor + arg[0] * num_taylor_per_var + m; Base* y = taylor + arg[1] * num_taylor_per_var + m; Base* z = taylor + i_z * num_taylor_per_var + m; for(size_t ell = 0; ell < r; ell++) z[ell] = x[ell] - y[ell]; } /*! Compute zero order forward mode Taylor coefficients for result of op = SubvvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op_0 */ template inline void forward_subvv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x[0] - y[0]; } /*! Compute reverse mode partial derivatives for result of op = SubvvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails reverse_binary_op */ template inline void reverse_subvv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Partial derivatives corresponding to arguments and result Base* px = partial + arg[0] * nc_partial; Base* py = partial + arg[1] * nc_partial; Base* pz = partial + i_z * nc_partial; // number of indices to access size_t i = d + 1; while(i) { --i; px[i] += pz[i]; py[i] -= pz[i]; } } // --------------------------- Subpv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = SubpvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op */ template inline void forward_subpv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; // Paraemter value Base x = parameter[ arg[0] ]; if( p == 0 ) { z[0] = x - y[0]; p++; } for(size_t d = p; d <= q; d++) z[d] = - y[d]; } /*! Multiple directions forward mode Taylor coefficients for op = SubpvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op_dir */ template inline void forward_subpv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; size_t m = (q-1) * r + 1; Base* y = taylor + arg[1] * num_taylor_per_var + m; Base* z = taylor + i_z * num_taylor_per_var + m; // Paraemter value for(size_t ell = 0; ell < r; ell++) z[ell] = - y[ell]; } /*! Compute zero order forward mode Taylor coefficient for result of op = SubpvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op_0 */ template inline void forward_subpv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 ); // Paraemter value Base x = parameter[ arg[0] ]; // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x - y[0]; } /*! Compute reverse mode partial derivative for result of op = SubpvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails reverse_binary_op */ template inline void reverse_subpv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Partial derivatives corresponding to arguments and result Base* py = partial + arg[1] * nc_partial; Base* pz = partial + i_z * nc_partial; // number of indices to access size_t i = d + 1; while(i) { --i; py[i] -= pz[i]; } } // --------------------------- Subvp ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = SubvvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_binary_op */ template inline void forward_subvp_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* z = taylor + i_z * cap_order; // Parameter value Base y = parameter[ arg[1] ]; if( p == 0 ) { z[0] = x[0] - y; p++; } for(size_t d = p; d <= q; d++) z[d] = x[d]; } /*! Multiple directions forward mode Taylor coefficients for op = SubvvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_binary_op_dir */ template inline void forward_subvp_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + arg[0] * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; // Parameter value size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) z[m+ell] = x[m+ell]; } /*! Compute zero order forward mode Taylor coefficients for result of op = SubvvOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_binary_op_0 */ template inline void forward_subvp_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 ); // Parameter value Base y = parameter[ arg[1] ]; // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x[0] - y; } /*! Compute reverse mode partial derivative for result of op = SubvpOp. The C++ source code corresponding to this operation is \verbatim z = x - y \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails reverse_binary_op */ template inline void reverse_subvp_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Partial derivatives corresponding to arguments and result Base* px = partial + arg[0] * nc_partial; Base* pz = partial + i_z * nc_partial; // number of indices to access size_t i = d + 1; while(i) { --i; px[i] += pz[i]; } } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/cppad_assert.hpp0000644000176200001440000001507314536067013020651 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_CPPAD_ASSERT_INCLUDED # define CPPAD_CPPAD_ASSERT_INCLUDED # define CPPAD_UNUSED(x) ((void)(x)) /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /*! \file cppad_assert.hpp Define the CppAD error checking macros (all of which begin with CPPAD_ASSERT_) */ /* ------------------------------------------------------------------------------- $begin cppad_assert$$ $spell CppAD exp const bool $$ $index assert, error macro $$ $index error, assert macro$$ $index macro, error assert$$ $section CppAD Assertions During Execution$$ $head Syntax$$ $codei%CPPAD_ASSERT_KNOWN(%exp%, %msg%) %$$ $codei%CPPAD_ASSERT_UNKNOWN(%exp%)%$$ $head Purpose$$ These CppAD macros are used to detect and report errors. They are documented here because they correspond to the C++ source code that the error is reported at. $head NDEBUG$$ $index NDEBUG$$ If the preprocessor symbol $cref/NDEBUG/Faq/Speed/NDEBUG/$$ is defined, these macros do nothing; i.e., they are optimized out. $head Restriction$$ The CppAD user should not uses these macros. You can however write your own macros that do not begin with $code CPPAD$$ and that call the $cref/CppAD error handler/ErrorHandler/$$. $subhead Known$$ $index CPPAD_ASSERT_KNOWN$$ The $code CPPAD_ASSERT_KNOWN$$ macro is used to check for an error with a known cause. For example, many CppAD routines uses these macros to make sure their arguments conform to their specifications. $subhead Unknown$$ $index CPPAD_ASSERT_UNKNOWN$$ The $code CPPAD_ASSERT_UNKNOWN$$ macro is used to check that the CppAD internal data structures conform as expected. If this is not the case, CppAD does not know why the error has occurred; for example, the user may have written past the end of an allocated array. $head Exp$$ The argument $icode exp$$ is a C++ source code expression that results in a $code bool$$ value that should be true. If it is false, an error has occurred. This expression may be execute any number of times (including zero times) so it must have not side effects. $head Msg$$ The argument $icode msg$$ has prototype $codei% const char *%msg% %$$ and contains a $code '\0'$$ terminated character string. This string is a description of the error corresponding to $icode exp$$ being false. $head Error Handler$$ These macros use the $cref/CppAD error handler/ErrorHandler/$$ to report errors. This error handler can be replaced by the user. $end ------------------------------------------------------------------------------ */ # include # include # include # ifdef _OPENMP # include # endif /*! \def CPPAD_ASSERT_KNOWN(exp, msg) Check that \a exp is true, if not print \a msg and terminate execution. The C++ expression \a exp is expected to be true. If it is false, the CppAD use has made an error that is described by \a msg. If the preprocessor symbol \a NDEBUG is not defined, and \a exp is false, this macro will report the source code line number at which this expected result occurred. In addition, it will print the specified error message \a msg. */ # ifdef NDEBUG # define CPPAD_ASSERT_KNOWN(exp, msg) // do nothing # else # define CPPAD_ASSERT_KNOWN(exp, msg) \ { if( ! ( exp ) ) \ CppAD::ErrorHandler::Call( \ true , \ __LINE__ , \ __FILE__ , \ #exp , \ msg ); \ } # endif /*! \def CPPAD_ASSERT_UNKNOWN(exp) Check that \a exp is true, if not terminate execution. The C++ expression \a exp is expected to be true. If it is false, CppAD has detected an error but does not know the cause of the error. If the preprocessor symbol \a NDEBUG is not defined, and \a exp is false, this macro will report the source code line number at which this expected result occurred. */ # ifdef NDEBUG # define CPPAD_ASSERT_UNKNOWN(exp) // do nothing # else # define CPPAD_ASSERT_UNKNOWN(exp) \ { if( ! ( exp ) ) \ CppAD::ErrorHandler::Call( \ false , \ __LINE__ , \ __FILE__ , \ #exp , \ "" ); \ } # endif /*! \def CPPAD_ASSERT_NARG_NRES(op, n_arg, n_res) Check that operator \a op has the specified number of of arguments and results. If \a NDEBUG is not defined and either the number of arguments or the number of results are not as expected, execution is terminated and the source code line number is reported. */ # define CPPAD_ASSERT_NARG_NRES(op, n_arg, n_res) \ CPPAD_ASSERT_UNKNOWN( NumArg(op) == n_arg ) \ CPPAD_ASSERT_UNKNOWN( NumRes(op) == n_res ) /*! \def CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL Check that the first call to a routine is not during parallel execution mode. If \c NDEBUG is defined, this macro has no effect (not even the definition of (\c assert_first_call). Otherwise, the variable \code static bool assert_first_call \endcode is defined and if the first call is executed in parallel mode, execution is terminated and the source code line number is reported. */ # ifdef NDEBUG # define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # else # define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL \ static bool assert_first_call = true; \ if( assert_first_call ) \ { CPPAD_ASSERT_KNOWN( \ ! (CppAD::thread_alloc::in_parallel() ), \ "In parallel mode and parallel_setup has not been called." \ ); \ assert_first_call = false; \ } # endif /*! \def CPPAD_ASSERT_ARG_BEFORE_RESULT Check that operator arguments come before result. If \c NDEBUG is defined, this macro has no effect, otherwise it calls the function assert_arg_before_result. */ # ifdef NDEBUG # define CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, result) # else # define CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, result) \ assert_arg_before_result(op, arg, result) # endif # endif TMB/inst/include/cppad/local/math_other.hpp0000644000176200001440000000212214536067013020322 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_MATH_OTHER_INCLUDED # define CPPAD_MATH_OTHER_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin MathOther$$ $spell atan $$ $index other, AD math$$ $index math, AD other$$ $index AD, other math$$ $section Other AD Math Functions$$ $childtable% cppad/local/abs.hpp% cppad/local/sign.hpp% cppad/local/atan2.hpp% cppad/local/erf.hpp% cppad/local/pow.hpp% cppad/local/limits.hpp %$$ $end */ # include # include # include # include # include # endif TMB/inst/include/cppad/local/comp_op.hpp0000644000176200001440000001764214536067013017641 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_COMP_OP_INCLUDED # define CPPAD_COMP_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file comp_op.hpp Zero order forward mode check how many comparisons changed. */ // -------------------------------- <= ----------------------------------- /*! Zero order forward mode comparison check that left <= right \param count It the condition is not true, ths counter is incremented by one. \param arg parameter[ arg[0] ] is the left operand and taylor[ arg[1] * cap_order + 0 ] is the zero order Taylor coefficient for the right operand. \param parameter vector of parameter values. \param cap_order number of Taylor coefficients allocated for each variable \param taylor vector of taylor coefficients. */ template inline void forward_lepv_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LepvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(LepvOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base x = parameter[ arg[0] ]; Base* y = taylor + arg[1] * cap_order; count += GreaterThanZero(x - y[0]); } /*! Zero order forward mode comparison check that left <= right \param count It the condition is not true, ths counter is incremented by one. \param arg taylor[ arg[0] * cap_order + 0 ] is the zero order Taylor coefficient for the left operand and parameter[ arg[1] ] is the right operand \param parameter vector of parameter values. \param cap_order number of Taylor coefficients allocated for each variable \param taylor vector of taylor coefficients. */ template inline void forward_levp_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LevpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(LevpOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base y = parameter[ arg[1] ]; count += GreaterThanZero(x[0] - y); } /*! Zero order forward mode comparison check that left <= right \param count It the condition is not true, ths counter is incremented by one. \param arg taylor[ arg[0] * cap_order + 0 ] is the zero order Taylor coefficient for the left operand and taylor[ arg[1] * cap_order + 0 ] is the zero order Taylor coefficient for the right operand. \param parameter vector of parameter values. \param cap_order number of Taylor coefficients allocated for each variable \param taylor vector of taylor coefficients. */ template inline void forward_levv_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LevvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(LevvOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; count += GreaterThanZero(x[0] - y[0]); } // ------------------------------- < ------------------------------------- /*! Zero order forward mode comparison check that left < right \copydetails forward_lepv_op_0 */ template inline void forward_ltpv_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LtpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(LtpvOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base x = parameter[ arg[0] ]; Base* y = taylor + arg[1] * cap_order; count += GreaterThanOrZero(x - y[0]); } /*! Zero order forward mode comparison check that left < right \copydetails forward_levp_op_0 */ template inline void forward_ltvp_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LtvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(LtvpOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base y = parameter[ arg[1] ]; count += GreaterThanOrZero(x[0] - y); } /*! Zero order forward mode comparison check that left < right \copydetails forward_levv_op_0 */ template inline void forward_ltvv_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LtvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(LtvvOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; count += GreaterThanOrZero(x[0] - y[0]); } // ------------------------------ == ------------------------------------- /*! Zero order forward mode comparison check that left == right \copydetails forward_lepv_op_0 */ template inline void forward_eqpv_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(EqpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(EqpvOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base x = parameter[ arg[0] ]; Base* y = taylor + arg[1] * cap_order; count += (x != y[0]); } /*! Zero order forward mode comparison check that left == right \copydetails forward_levv_op_0 */ template inline void forward_eqvv_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(EqvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(EqvvOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; count += (x[0] != y[0]); } // -------------------------------- != ----------------------------------- /*! Zero order forward mode comparison check that left != right \copydetails forward_lepv_op_0 */ template inline void forward_nepv_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(NepvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(NepvOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base x = parameter[ arg[0] ]; Base* y = taylor + arg[1] * cap_order; count += (x == y[0]); } /*! Zero order forward mode comparison check that left != right \copydetails forward_levv_op_0 */ template inline void forward_nevv_op_0( size_t& count , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(NevvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(NevvOp) == 0 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; count += (x[0] == y[0]); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/compare.hpp0000644000176200001440000002515214536067013017626 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_COMPARE_INCLUDED # define CPPAD_COMPARE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin Compare$$ $spell cos Op bool const $$ $index binary, AD compare operator$$ $index AD, binary compare operator$$ $index compare, AD binary operator$$ $index operator, AD binary compare$$ $index <, AD operator$$ $index <=, AD operator$$ $index >, AD operator$$ $index >=, AD operator$$ $index ==, AD operator$$ $index !=, AD operator$$ $section AD Binary Comparison Operators$$ $head Syntax$$ $icode%b% = %x% %Op% %y%$$ $head Purpose$$ Compares two operands where one of the operands is an $codei%AD<%Base%>%$$ object. The comparison has the same interpretation as for the $icode Base$$ type. $head Op$$ The operator $icode Op$$ is one of the following: $table $bold Op$$ $pre $$ $cnext $bold Meaning$$ $rnext $code <$$ $cnext is $icode x$$ less than $icode y$$ $rnext $code <=$$ $cnext is $icode x$$ less than or equal $icode y$$ $rnext $code >$$ $cnext is $icode x$$ greater than $icode y$$ $rnext $code >=$$ $cnext is $icode x$$ greater than or equal $icode y$$ $rnext $code ==$$ $cnext is $icode x$$ equal to $icode y$$ $rnext $code !=$$ $cnext is $icode x$$ not equal to $icode y$$ $tend $head x$$ The operand $icode x$$ has prototype $codei% const %Type% &%x% %$$ where $icode Type$$ is $codei%AD<%Base%>%$$, $icode Base$$, or $code int$$. $head y$$ The operand $icode y$$ has prototype $codei% const %Type% &%y% %$$ where $icode Type$$ is $codei%AD<%Base%>%$$, $icode Base$$, or $code int$$. $head b$$ The result $icode b$$ has type $codei% bool %b% %$$ $head Operation Sequence$$ The result of this operation is a $code bool$$ value (not an $cref/AD of Base/glossary/AD of Base/$$ object). Thus it will not be recorded as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $pre $$ For example, suppose $icode x$$ and $icode y$$ are $codei%AD<%Base%>%$$ objects, the tape corresponding to $codei%AD<%Base%>%$$ is recording, $icode b$$ is true, and the subsequent code is $codei% if( %b% ) %y% = cos(%x%); else %y% = sin(%x%); %$$ only the assignment $icode%y% = cos(%x%)%$$ is recorded on the tape (if $icode x$$ is a $cref/parameter/glossary/Parameter/$$, nothing is recorded). The $cref CompareChange$$ function can yield some information about changes in comparison operation results. You can use $cref CondExp$$ to obtain comparison operations that depends on the $cref/independent variable/glossary/Tape/Independent Variable/$$ values with out re-taping the AD sequence of operations. $head Assumptions$$ If one of the $icode Op$$ operators listed above is used with an $codei%AD<%Base%>%$$ object, it is assumed that the same operator is supported by the base type $icode Base$$. $head Example$$ $children% example/compare.cpp %$$ The file $cref compare.cpp$$ contains an example and test of these operations. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { // -------------------------------- < -------------------------- template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool operator < (const AD &left , const AD &right) { bool result = (left.value_ < right.value_); bool var_left = Variable(left); bool var_right = Variable(right); ADTape *tape = CPPAD_NULL; if( var_left ) { tape = left.tape_this(); if( var_right ) { if( result ) { tape->Rec_.PutOp(LtvvOp); tape->Rec_.PutArg(left.taddr_, right.taddr_); } else { tape->Rec_.PutOp(LevvOp); tape->Rec_.PutArg(right.taddr_, left.taddr_); } } else { addr_t arg1 = tape->Rec_.PutPar(right.value_); if( result ) { tape->Rec_.PutOp(LtvpOp); tape->Rec_.PutArg(left.taddr_, arg1); } else { tape->Rec_.PutOp(LepvOp); tape->Rec_.PutArg(arg1, left.taddr_); } } } else if ( var_right ) { tape = right.tape_this(); addr_t arg0 = tape->Rec_.PutPar(left.value_); if( result ) { tape->Rec_.PutOp(LtpvOp); tape->Rec_.PutArg(arg0, right.taddr_); } else { tape->Rec_.PutOp(LevpOp); tape->Rec_.PutArg(right.taddr_, arg0); } } return result; } // convert other cases into the case above CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(<) // -------------------------------- <= ------------------------- template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool operator <= (const AD &left , const AD &right) { bool result = (left.value_ <= right.value_); bool var_left = Variable(left); bool var_right = Variable(right); ADTape *tape = CPPAD_NULL; if( var_left ) { tape = left.tape_this(); if( var_right ) { if( result ) { tape->Rec_.PutOp(LevvOp); tape->Rec_.PutArg(left.taddr_, right.taddr_); } else { tape->Rec_.PutOp(LtvvOp); tape->Rec_.PutArg(right.taddr_, left.taddr_); } } else { addr_t arg1 = tape->Rec_.PutPar(right.value_); if( result ) { tape->Rec_.PutOp(LevpOp); tape->Rec_.PutArg(left.taddr_, arg1); } else { tape->Rec_.PutOp(LtpvOp); tape->Rec_.PutArg(arg1, left.taddr_); } } } else if ( var_right ) { tape = right.tape_this(); addr_t arg0 = tape->Rec_.PutPar(left.value_); if( result ) { tape->Rec_.PutOp(LepvOp); tape->Rec_.PutArg(arg0, right.taddr_); } else { tape->Rec_.PutOp(LtvpOp); tape->Rec_.PutArg(right.taddr_, arg0); } } return result; } // convert other cases into the case above CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(<=) // -------------------------------- > -------------------------- template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool operator > (const AD &left , const AD &right) { bool result = (left.value_ > right.value_); bool var_left = Variable(left); bool var_right = Variable(right); ADTape *tape = CPPAD_NULL; if( var_left ) { tape = left.tape_this(); if( var_right ) { if( result ) { tape->Rec_.PutOp(LtvvOp); tape->Rec_.PutArg(right.taddr_, left.taddr_); } else { tape->Rec_.PutOp(LevvOp); tape->Rec_.PutArg(left.taddr_, right.taddr_); } } else { addr_t arg1 = tape->Rec_.PutPar(right.value_); if( result ) { tape->Rec_.PutOp(LtpvOp); tape->Rec_.PutArg(arg1, left.taddr_); } else { tape->Rec_.PutOp(LevpOp); tape->Rec_.PutArg(left.taddr_, arg1); } } } else if ( var_right ) { tape = right.tape_this(); addr_t arg0 = tape->Rec_.PutPar(left.value_); if( result ) { tape->Rec_.PutOp(LtvpOp); tape->Rec_.PutArg(right.taddr_, arg0); } else { tape->Rec_.PutOp(LepvOp); tape->Rec_.PutArg(arg0, right.taddr_); } } return result; } // convert other cases into the case above CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(>) // -------------------------------- >= ------------------------- template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool operator >= (const AD &left , const AD &right) { bool result = (left.value_ >= right.value_); bool var_left = Variable(left); bool var_right = Variable(right); ADTape *tape = CPPAD_NULL; if( var_left ) { tape = left.tape_this(); if( var_right ) { if( result ) { tape->Rec_.PutOp(LevvOp); tape->Rec_.PutArg(right.taddr_, left.taddr_); } else { tape->Rec_.PutOp(LtvvOp); tape->Rec_.PutArg(left.taddr_, right.taddr_); } } else { addr_t arg1 = tape->Rec_.PutPar(right.value_); if( result ) { tape->Rec_.PutOp(LepvOp); tape->Rec_.PutArg(arg1, left.taddr_); } else { tape->Rec_.PutOp(LtvpOp); tape->Rec_.PutArg(left.taddr_, arg1); } } } else if ( var_right ) { tape = right.tape_this(); addr_t arg0 = tape->Rec_.PutPar(left.value_); if( result ) { tape->Rec_.PutOp(LevpOp); tape->Rec_.PutArg(right.taddr_, arg0); } else { tape->Rec_.PutOp(LtpvOp); tape->Rec_.PutArg(arg0, right.taddr_); } } return result; } // convert other cases into the case above CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(>=) // -------------------------------- == ------------------------- template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool operator == (const AD &left , const AD &right) { bool result = (left.value_ == right.value_); bool var_left = Variable(left); bool var_right = Variable(right); ADTape *tape = CPPAD_NULL; if( var_left ) { tape = left.tape_this(); if( var_right ) { tape->Rec_.PutArg(left.taddr_, right.taddr_); if( result ) tape->Rec_.PutOp(EqvvOp); else tape->Rec_.PutOp(NevvOp); } else { addr_t arg1 = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(arg1, left.taddr_); if( result ) tape->Rec_.PutOp(EqpvOp); else tape->Rec_.PutOp(NepvOp); } } else if ( var_right ) { tape = right.tape_this(); addr_t arg0 = tape->Rec_.PutPar(left.value_); tape->Rec_.PutArg(arg0, right.taddr_); if( result ) tape->Rec_.PutOp(EqpvOp); else tape->Rec_.PutOp(NepvOp); } return result; } // convert other cases into the case above CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(==) // -------------------------------- != ------------------------- template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool operator != (const AD &left , const AD &right) { bool result = (left.value_ != right.value_); bool var_left = Variable(left); bool var_right = Variable(right); ADTape *tape = CPPAD_NULL; if( var_left ) { tape = left.tape_this(); if( var_right ) { tape->Rec_.PutArg(left.taddr_, right.taddr_); if( result ) tape->Rec_.PutOp(NevvOp); else tape->Rec_.PutOp(EqvvOp); } else { addr_t arg1 = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(arg1, left.taddr_); if( result ) tape->Rec_.PutOp(NepvOp); else tape->Rec_.PutOp(EqpvOp); } } else if ( var_right ) { tape = right.tape_this(); addr_t arg0 = tape->Rec_.PutPar(left.value_); tape->Rec_.PutArg(arg0, right.taddr_); if( result ) tape->Rec_.PutOp(NepvOp); else tape->Rec_.PutOp(EqpvOp); } return result; } // convert other cases into the case above CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(!=) } // END CppAD namespace # endif TMB/inst/include/cppad/local/base_cond_exp.hpp0000644000176200001440000001640014536067013020765 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BASE_COND_EXP_INCLUDED # define CPPAD_BASE_COND_EXP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin base_cond_exp$$ $spell alloc Rel hpp enum namespace Op Lt Le Eq Ge Gt Ne cond exp const adolc CppAD inline $$ $section Base Type Requirements for Conditional Expressions$$ $index CondExp, base require$$ $index base, CondExp require$$ $index require, base CondExp$$ $head Purpose$$ These definitions are required by the user's code to support the $codei%AD<%Base%>%$$ type for $cref CondExp$$ operations: $head CompareOp$$ The following $code enum$$ type is used in the specifications below: $codep namespace CppAD { // The conditional expression operator enum type enum CompareOp { CompareLt, // less than CompareLe, // less than or equal CompareEq, // equal CompareGe, // greater than or equal CompareGt, // greater than CompareNe // not equal }; } $$ $head CondExpTemplate$$ The type $icode Base$$ must support the syntax $codei% %result% = CppAD::CondExpOp( %cop%, %left%, %right%, %exp_if_true%, %exp_if_false% ) %$$ which computes implements the corresponding $cref CondExp$$ function when the result has prototype $codei% %Base% %result% %$$ The argument $icode cop$$ has prototype $codei% enum CppAD::CompareOp %cop% %$$ The other arguments have the prototype $codei% const %Base%& %left% const %Base%& %right% const %Base%& %exp_if_true% const %Base%& %exp_if_false% %$$ $subhead Ordered Type$$ If $icode Base$$ is a relatively simple type that supports $code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators its $code CondExpOp$$ function can be defined by $codei% namespace CppAD { inline %Base% CondExpOp( enum CppAD::CompareOp cop , const %Base% &left , const %Base% &right , const %Base% &exp_if_true , const %Base% &exp_if_false ) { return CondExpTemplate( cop, left, right, trueCase, falseCase); } } %$$ For example, see $cref/double CondExpOp/base_alloc.hpp/CondExpOp/$$. For an example of and implementation of $code CondExpOp$$ with a more involved $icode Base$$ type see $cref/adolc CondExpOp/base_adolc.hpp/CondExpOp/$$. $subhead Not Ordered$$ If the type $icode Base$$ does not support ordering, the $code CondExpOp$$ function does not make sense. In this case one might (but need not) define $code CondExpOp$$ as follows: $codei% namespace CppAD { inline %Base% CondExpOp( enum CompareOp cop , const %Base% &left , const %Base% &right , const %Base% &exp_if_true , const %Base% &exp_if_false ) { // attempt to use CondExp with a %Base% argument assert(0); return %Base%(0); } } %$$ For example, see $cref/complex CondExpOp/base_complex.hpp/CondExpOp/$$. $head CondExpRel$$ $index CPPAD_COND_EXP_REL$$ The macro invocation $codei% CPPAD_COND_EXP_REL(%Base%) %$$ uses $code CondExpOp$$ above to define the following functions $codei% CondExpLt(%left%, %right%, %exp_if_true%, %exp_if_false%) CondExpLe(%left%, %right%, %exp_if_true%, %exp_if_false%) CondExpEq(%left%, %right%, %exp_if_true%, %exp_if_false%) CondExpGe(%left%, %right%, %exp_if_true%, %exp_if_false%) CondExpGt(%left%, %right%, %exp_if_true%, %exp_if_false%) %$$ where the arguments have type $icode Base$$. This should be done inside of the CppAD namespace. For example, see $cref/base_alloc/base_alloc.hpp/CondExpRel/$$. $end */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file base_cond_exp.hpp CondExp operations that aid in meeting Base type requirements. */ /*! \def CPPAD_COND_EXP_BASE_REL(Type, Rel, Op) This macro defines the operation \verbatim CondExpRel(left, right, exp_if_true, exp_if_false) \endverbatim The argument \c Type is the \c Base type for this base require operation. The argument \c Rel is one of \c Lt, \c Le, \c Eq, \c Ge, \c Gt. The argument \c Op is the corresponding \c CompareOp value. */ # define CPPAD_COND_EXP_BASE_REL(Type, Rel, Op) \ inline Type CondExp##Rel( \ const Type& left , \ const Type& right , \ const Type& exp_if_true , \ const Type& exp_if_false ) \ { return CondExpOp(Op, left, right, exp_if_true, exp_if_false); \ } /*! \def CPPAD_COND_EXP_REL(Type) The macro defines the operations \verbatim CondExpLt(left, right, exp_if_true, exp_if_false) CondExpLe(left, right, exp_if_true, exp_if_false) CondExpEq(left, right, exp_if_true, exp_if_false) CondExpGe(left, right, exp_if_true, exp_if_false) CondExpGt(left, right, exp_if_true, exp_if_false) \endverbatim The argument \c Type is the \c Base type for this base require operation. */ # define CPPAD_COND_EXP_REL(Type) \ CPPAD_COND_EXP_BASE_REL(Type, Lt, CompareLt) \ CPPAD_COND_EXP_BASE_REL(Type, Le, CompareLe) \ CPPAD_COND_EXP_BASE_REL(Type, Eq, CompareEq) \ CPPAD_COND_EXP_BASE_REL(Type, Ge, CompareGe) \ CPPAD_COND_EXP_BASE_REL(Type, Gt, CompareGt) /*! Template function to implement Conditional Expressions for simple types that have comparision operators. \tparam CompareType is the type of the left and right operands to the comparision operator. \tparam ResultType is the type of the result, which is the same as \c CompareType except during forward and reverse mode sparese calculations. \param cop specifices which comparision to use; i.e., $code <$$, $code <=$$, $code ==$$, $code >=$$, $code >$$, or $code !=$$. \param left is the left operand to the comparision operator. \param right is the right operand to the comparision operator. \param exp_if_true is the return value is the comparision results in true. \param exp_if_false is the return value is the comparision results in false. \return see \c exp_if_true and \c exp_if_false above. */ template ResultType CondExpTemplate( enum CompareOp cop , const CompareType& left , const CompareType& right , const ResultType& exp_if_true , const ResultType& exp_if_false ) { ResultType returnValue; switch( cop ) { case CompareLt: if( left < right ) returnValue = exp_if_true; else returnValue = exp_if_false; break; case CompareLe: if( left <= right ) returnValue = exp_if_true; else returnValue = exp_if_false; break; case CompareEq: if( left == right ) returnValue = exp_if_true; else returnValue = exp_if_false; break; case CompareGe: if( left >= right ) returnValue = exp_if_true; else returnValue = exp_if_false; break; case CompareGt: if( left > right ) returnValue = exp_if_true; else returnValue = exp_if_false; break; default: CPPAD_ASSERT_UNKNOWN(0); returnValue = exp_if_true; } return returnValue; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/atomic_base.hpp0000644000176200001440000012317514536067013020452 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ATOMIC_BASE_INCLUDED # define CPPAD_ATOMIC_BASE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file atomic_base.hpp Base class for atomic user operations. */ template class atomic_base { // =================================================================== public: enum option_enum { bool_sparsity_enum, set_sparsity_enum}; private: // ------------------------------------------------------ // constants // /// index of this object in class_object const size_t index_; // ----------------------------------------------------- // variables // /// sparsity pattern this object is currently using /// (set by constructor and option member functions) option_enum sparsity_; /// temporary work space used afun, declared here to avoid memory /// allocation/deallocation for each call to afun vector afun_vx_[CPPAD_MAX_NUM_THREADS]; vector afun_vy_[CPPAD_MAX_NUM_THREADS]; vector afun_tx_[CPPAD_MAX_NUM_THREADS]; vector afun_ty_[CPPAD_MAX_NUM_THREADS]; // ----------------------------------------------------- // static member functions // /// List of all the object in this class static std::vector& class_object(void) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static std::vector list_; return list_; } /// List of names for each object in this class static std::vector& class_name(void) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static std::vector list_; return list_; } // ===================================================================== public: // ----------------------------------------------------- // member functions not in user API // /// current sparsity setting option_enum sparsity(void) const { return sparsity_; } /// Name corresponding to a base_atomic object const std::string& afun_name(void) const { return class_name()[index_]; } /* $begin atomic_ctor$$ $spell sq std afun arg CppAD bool ctor const matrix_mul.hpp $$ $section Atomic Function Constructor$$ $index constructor, atomic function$$ $index atomic, function constructor$$ $index function, atomic constructor$$ $head Syntax$$ $icode%atomic_user afun%(%ctor_arg_list%) %$$ $codei%atomic_base<%Base%>(%name%) %$$ $head atomic_user$$ $subhead ctor_arg_list$$ Is a list of arguments for the $icode atomic_user$$ constructor. $subhead afun$$ The object $icode afun$$ must stay in scope for as long as the corresponding atomic function is used. This includes use by any $cref/ADFun/ADFun/$$ that has this $icode atomic_user$$ operation in its $cref/operation sequence/glossary/Operation/Sequence/$$. $subhead Implementation$$ The user defined $icode atomic_user$$ class is a publicly derived class of $codei%atomic_base<%Base%>%$$. It should be declared as follows: $codei% class %atomic_user% : public CppAD::atomic_base<%Base%> { public: %atomic_user%(%ctor_arg_list%) : atomic_base<%Base%>(%name%) %...% }; %$$ where $icode ...$$ denotes the rest of the implementation of the derived class. This includes completing the constructor and all the virtual functions that have their $code atomic_base$$ implementations replaced by $icode atomic_user$$ implementations. $head atomic_base$$ $subhead Restrictions$$ The $code atomic_base$$ constructor cannot be called in $cref/parallel/ta_in_parallel/$$ mode. $subhead Base$$ The template parameter determines the $icode Base$$ type for this $codei%AD<%Base%>%$$ atomic operation. $subhead name$$ This $icode atomic_base$$ constructor argument has either of the following prototypes $codei% const char* %name% const std::string& %name% %$$ It is the name for this atomic function and is used for error reporting. The suggested value for $icode name$$ is $icode afun$$ or $icode atomic_user$$, i.e., the name of the corresponding atomic object or class. $head Examples$$ $subhead Define Constructor$$ The following are links to user atomic function constructor definitions: $cref%get_started.cpp%atomic_get_started.cpp%Constructor%$$, $cref%norm_sq.cpp%atomic_norm_sq.cpp%Constructor%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%Constructor%$$, $cref%tangent.cpp%atomic_tangent.cpp%Constructor%$$, $cref%matrix_mul.hpp%atomic_matrix_mul.hpp%Constructor%$$. $subhead Use Constructor$$ The following are links to user atomic function constructor uses: $cref%get_started.cpp%atomic_get_started.cpp%Use Atomic Function%Constructor%$$, $cref%norm_sq.cpp%atomic_norm_sq.cpp%Use Atomic Function%Constructor%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%Use Atomic Function%Constructor%$$, $cref%tangent.cpp%atomic_tangent.cpp%Use Atomic Function%Constructor%$$, $cref%mat_mul.cpp%atomic_mat_mul.cpp%Use Atomic Function%Constructor%$$. $end */ /*! Base class for atomic_user functions. \tparam Base This class is used for defining an AD atomic operation y = f(x). */ /// make sure user does not invoke the default constructor atomic_base(void) { CPPAD_ASSERT_KNOWN(false, "Attempt to use the atomic_base default constructor" ); } /*! Constructor \param name name used for error reporting */ atomic_base( const std::string& name) : index_( class_object().size() ) , sparsity_( set_sparsity_enum ) { CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "atomic_base: constructor cannot be called in parallel mode." ); class_object().push_back(this); class_name().push_back(name); CPPAD_ASSERT_UNKNOWN( class_object().size() == class_name().size() ); } /// destructor informs CppAD that this atomic function with this index /// has dropped out of scope by setting its pointer to null virtual ~atomic_base(void) { CPPAD_ASSERT_UNKNOWN( class_object().size() > index_ ); // change object pointer to null, but leave name for error reporting class_object()[index_] = CPPAD_NULL; } /// atomic_base function object corresponding to a certain index static atomic_base* class_object(size_t index) { CPPAD_ASSERT_UNKNOWN( class_object().size() > index ); return class_object()[index]; } /// atomic_base function name corresponding to a certain index static const std::string& class_name(size_t index) { CPPAD_ASSERT_UNKNOWN( class_name().size() > index ); return class_name()[index]; } /* $begin atomic_option$$ $spell sq enum afun bool CppAD std typedef $$ $section Set Atomic Function Options$$ $index atomic, options$$ $index options, atomic$$ $head Syntax$$ $icode%afun%.option(%option_value%)%$$ $head atomic_sparsity$$ $index atomic_sparsity$$ $index sparsity, atomic$$ You can used this option to set the type used for $icode afun$$ sparsity patterns. This does not apply individual calls to $icode afun$$, but rather all its uses between when the sparsity pattern is set and when it is changed. If neither the $code set_sparsity_enum$$ or $code bool_sparsity_enum$$ option is set, the type for $icode atomic_sparsity$$ is one of the two choices below (and otherwise unspecified). $subhead bool_sparsity_enum$$ $index bool_sparsity_enum$$ If $icode option_value$$ is $codei%atomic_base<%Base%>::bool_sparsity_enum%$$, then the type used by $icode afun$$ for $cref/sparsity patterns/glossary/Sparsity Pattern/$$, (after the option is set) will be $codei% typedef CppAD::vector %atomic_sparsity% %$$ If $icode r$$ is a sparsity pattern for a matrix $latex R \in B^{p \times q}$$: $icode%r%.size() == %p% * %q%$$. $subhead set_sparsity_enum$$ $index set_sparsity_enum$$ If $icode option_value$$ is $icode%atomic_base<%Base%>::set_sparsity_enum%$$, then the type used by $icode afun$$ for $cref/sparsity patterns/glossary/Sparsity Pattern/$$, (after the option is set) will be $codei% typedef CppAD::vector< std::set > %atomic_sparsity% %$$ If $icode r$$ is a sparsity pattern for a matrix $latex R \in B^{p \times q}$$: $icode%r%.size() == %p%$$, and for $latex i = 0 , \ldots , p-1$$, the elements of $icode%r%[%i%]%$$ are between zero and $latex q-1$$ inclusive. $end */ void option(enum option_enum option_value) { switch( option_value ) { case bool_sparsity_enum: case set_sparsity_enum: sparsity_ = option_value; break; default: CPPAD_ASSERT_KNOWN( false, "atoic_base::option: option_value is not valid" ); } return; } /* ----------------------------------------------------------------------------- $begin atomic_afun$$ $spell sq mul afun const CppAD $$ $section Using AD Version of Atomic Function$$ $index atomic, use function$$ $head Syntax$$ $icode%afun%(%ax%, %ay%)%$$ $head Purpose$$ Given $icode ax$$, this call computes the corresponding value of $icode ay$$. If $codei%AD<%Base%>%$$ operations are being recorded, it enters the computation as an atomic operation in the recording; see $cref/start recording/Independent/Start Recording/$$. $head ADVector$$ The type $icode ADVector$$ must be a $cref/simple vector class/SimpleVector/$$ with elements of type $codei%AD<%Base%>%$$; see $cref/Base/atomic_ctor/atomic_base/Base/$$. $head afun$$ is a $cref/atomic_user/atomic_ctor/atomic_user/$$ object and this $icode afun$$ function call is implemented by the $cref/atomic_base/atomic_ctor/atomic_base/$$ class. $head ax$$ This argument has prototype $codei% const %ADVector%& %ax% %$$ and size must be equal to $icode n$$. It specifies vector $latex x \in B^n$$ at which an $codei%AD<%Base%>%$$ version of $latex y = f(x)$$ is to be evaluated; see $cref/Base/atomic_ctor/atomic_base/Base/$$. $head ay$$ This argument has prototype $codei% %ADVector%& %ay% %$$ and size must be equal to $icode m$$. The input values of its elements are not specified (must not matter). Upon return, it is an $codei%AD<%Base%>%$$ version of $latex y = f(x)$$. $head Examples$$ The following files contain example uses of the AD version of atomic functions during recording: $cref%get_started.cpp%atomic_get_started.cpp%Use Atomic Function%Recording%$$, $cref%norm_sq.cpp%atomic_norm_sq.cpp%Use Atomic Function%Recording%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%Use Atomic Function%Recording%$$, $cref%tangent.cpp%atomic_tangent.cpp%Use Atomic Function%Recording%$$, $cref%matrix_mul.cpp%atomic_mat_mul.cpp%Use Atomic Function%Recording%$$. $end ----------------------------------------------------------------------------- */ /*! Implement the user call to afun(ax, ay) and old_atomic call to afun(ax, ay, id). \tparam ADVector A simple vector class with elements of type AD. \param id optional extra information vector that is just passed through by CppAD, and used by old_atomic derived class (not other derived classes). This is an extra parameter to the virtual callbacks for old_atomic; see the set_id member function. \param ax is the argument vector for this call, ax.size() determines the number of arguments. \param ay is the result vector for this call, ay.size() determines the number of results. */ template void operator()( const ADVector& ax , ADVector& ay , size_t id = 0 ) { size_t i, j; size_t n = ax.size(); size_t m = ay.size(); # ifndef NDEBUG bool ok; std::string msg = "atomic_base: " + afun_name() + ".eval: "; if( (n == 0) | (m == 0) ) { msg += "ax.size() or ay.size() is zero"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif size_t thread = thread_alloc::thread_num(); vector & tx = afun_tx_[thread]; vector & ty = afun_ty_[thread]; vector & vx = afun_vx_[thread]; vector & vy = afun_vy_[thread]; // if( vx.size() != n ) { vx.resize(n); tx.resize(n); } if( vy.size() != m ) { vy.resize(m); ty.resize(m); } // // Determine tape corresponding to variables in ax tape_id_t tape_id = 0; ADTape* tape = CPPAD_NULL; for(j = 0; j < n; j++) { tx[j] = ax[j].value_; vx[j] = Variable( ax[j] ); if( vx[j] ) { if( tape_id == 0 ) { tape = ax[j].tape_this(); tape_id = ax[j].tape_id_; CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL ); } # ifndef NDEBUG if( tape_id != ax[j].tape_id_ ) { msg += afun_name() + ": ax contains variables from different threads."; CPPAD_ASSERT_KNOWN(false, msg.c_str()); } # endif } } // Use zero order forward mode to compute values size_t p = 0, q = 0; set_id(id); # ifdef NDEBUG forward(p, q, vx, vy, tx, ty); # else ok = forward(p, q, vx, vy, tx, ty); if( ! ok ) { msg += afun_name() + ": ok is false for " "zero order forward mode calculation."; CPPAD_ASSERT_KNOWN(false, msg.c_str()); } # endif bool record_operation = false; for(i = 0; i < m; i++) { // pass back values ay[i].value_ = ty[i]; // initialize entire vector parameters (not in tape) ay[i].tape_id_ = 0; ay[i].taddr_ = 0; // we need to record this operation if // any of the eleemnts of ay are variables, record_operation |= vy[i]; } # ifndef NDEBUG if( record_operation & (tape == CPPAD_NULL) ) { msg += "all elements of vx are false but vy contains a true element"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif // if tape is not null, ay is on the tape if( record_operation ) { // Operator that marks beginning of this atomic operation CPPAD_ASSERT_UNKNOWN( NumRes(UserOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg(UserOp) == 4 ); tape->Rec_.PutArg(index_, id, n, m); tape->Rec_.PutOp(UserOp); // Now put n operators, one for each element of arugment vector CPPAD_ASSERT_UNKNOWN( NumRes(UsravOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumRes(UsrapOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg(UsravOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrapOp) == 1 ); for(j = 0; j < n; j++) { if( vx[j] ) { // information for an argument that is a variable tape->Rec_.PutArg(ax[j].taddr_); tape->Rec_.PutOp(UsravOp); } else { // information for an arugment that is parameter addr_t par = tape->Rec_.PutPar(ax[j].value_); tape->Rec_.PutArg(par); tape->Rec_.PutOp(UsrapOp); } } // Now put m operators, one for each element of result vector CPPAD_ASSERT_UNKNOWN( NumArg(UsrrpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(UsrrpOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumRes(UsrrvOp) == 1 ); for(i = 0; i < m; i++) { if( vy[i] ) { ay[i].taddr_ = tape->Rec_.PutOp(UsrrvOp); ay[i].tape_id_ = tape_id; } else { addr_t par = tape->Rec_.PutPar(ay[i].value_); tape->Rec_.PutArg(par); tape->Rec_.PutOp(UsrrpOp); } } // Put a duplicate UserOp at end of UserOp sequence tape->Rec_.PutArg(index_, id, n, m); tape->Rec_.PutOp(UserOp); } return; } /* ----------------------------------------------------------------------------- $begin atomic_forward$$ $spell sq mul.hpp hes afun vx vy ty Taylor const CppAD bool $$ $section Atomic Forward Mode$$ $index atomic, forward callback$$ $index forward, atomic callback$$ $index forward, atomic virtual$$ $head Syntax$$ $icode%ok% = %afun%.forward(%p%, %q%, %vx%, %vy%, %tx%, %ty%)%$$ $head Purpose$$ This virtual function is used by $cref atomic_afun$$ to evaluate function values. It is also used buy $cref/forward/Forward/$$ to compute function vales and derivatives. $head Implementation$$ This virtual function must be defined by the $cref/atomic_user/atomic_ctor/atomic_user/$$ class. It can just return $icode%ok% == false%$$ (and not compute anything) for values of $icode%q% > 0%$$ that are greater than those used by your $cref/forward/Forward/$$ mode calculations. $head p$$ The argument $icode p$$ has prototype $codei% size_t %p% %$$ It specifies the lowest order Taylor coefficient that we are evaluating. During calls to $cref atomic_afun$$, $icode%p% == 0%$$. $head q$$ The argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the highest order Taylor coefficient that we are evaluating. During calls to $cref atomic_afun$$, $icode%q% == 0%$$. $head vx$$ The $code forward$$ argument $icode vx$$ has prototype $codei% const CppAD::vector& %vx% %$$ The case $icode%vx%.size() > 0%$$ only occurs while evaluating a call to $cref atomic_afun$$. In this case, $icode%p% == %q% == 0%$$, $icode%vx%.size() == %n%$$, and for $latex j = 0 , \ldots , n-1$$, $icode%vx%[%j%]%$$ is true if and only if $icode%ax%[%j%]%$$ is a $cref/variable/glossary/Variable/$$ in the corresponding call to $codei% %afun%(%ax%, %ay%, %id%) %$$ If $icode%vx%.size() == 0%$$, then $icode%vy%.size() == 0%$$ and neither of these vectors should be used. $head vy$$ The $code forward$$ argument $icode vy$$ has prototype $codei% CppAD::vector& %vy% %$$ If $icode%vy%.size() == 0%$$, it should not be used. Otherwise, $icode%q% == 0%$$ and $icode%vy%.size() == %m%$$. The input values of the elements of $icode vy$$ are not specified (must not matter). Upon return, for $latex j = 0 , \ldots , m-1$$, $icode%vy%[%i%]%$$ is true if and only if $icode%ay%[%i%]%$$ is a variable (CppAD uses $icode vy$$ to reduce the necessary computations). $head tx$$ The argument $icode tx$$ has prototype $codei% const CppAD::vector<%Base%>& %tx% %$$ and $icode%tx%.size() == (%q%+1)*%n%$$. For $latex j = 0 , \ldots , n-1$$ and $latex k = 0 , \ldots , q$$, we use the Taylor coefficient notation $latex \[ \begin{array}{rcl} x_j^k & = & tx [ j * ( q + 1 ) + k ] \\ X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q \end{array} \] $$ Note that superscripts represent an index for $latex x_j^k$$ and an exponent for $latex t^k$$. Also note that the Taylor coefficients for $latex X(t)$$ correspond to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way: $latex \[ x_j^k = \frac{1}{ k ! } X_j^{(k)} (0) \] $$ $head ty$$ The argument $icode ty$$ has prototype $codei% CppAD::vector<%Base%>& %ty% %$$ and $icode%tx%.size() == (%q%+1)*%m%$$. Upon return, For $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , q$$, $latex \[ \begin{array}{rcl} Y_i (t) & = & f_i [ X(t) ] \\ Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q ) \\ ty [ i * ( q + 1 ) + k ] & = & y_i^k \end{array} \] $$ where $latex o( t^q ) / t^q \rightarrow 0$$ as $latex t \rightarrow 0$$. Note that superscripts represent an index for $latex y_j^k$$ and an exponent for $latex t^k$$. Also note that the Taylor coefficients for $latex Y(t)$$ correspond to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way: $latex \[ y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0) \] $$ If $latex p > 0$$, for $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , p-1$$, the input of $icode ty$$ satisfies $latex \[ ty [ i * ( q + 1 ) + k ] = y_i^k \]$$ and hence the corresponding elements need not be recalculated. $head ok$$ If the required results are calculated, $icode ok$$ should be true. Otherwise, it should be false. $head Discussion$$ For example, suppose that $icode%q% == 2%$$, and you know how to compute the function $latex f(x)$$, its first derivative $latex f^{(1)} (x)$$, and it component wise Hessian $latex f_i^{(2)} (x)$$. Then you can compute $icode ty$$ using the following formulas: $latex \[ \begin{array}{rcl} y_i^0 & = & Y(0) = f_i ( x^0 ) \\ y_i^1 & = & Y^{(1)} ( 0 ) = f_i^{(1)} ( x^0 ) X^{(1)} ( 0 ) = f_i^{(1)} ( x^0 ) x^1 \\ y_i^2 & = & \frac{1}{2 !} Y^{(2)} (0) \\ & = & \frac{1}{2} X^{(1)} (0)^\R{T} f_i^{(2)} ( x^0 ) X^{(1)} ( 0 ) + \frac{1}{2} f_i^{(1)} ( x^0 ) X^{(2)} ( 0 ) \\ & = & \frac{1}{2} (x^1)^\R{T} f_i^{(2)} ( x^0 ) x^1 + f_i^{(1)} ( x^0 ) x^2 \end{array} \] $$ For $latex i = 0 , \ldots , m-1$$, and $latex k = 0 , 1 , 2$$, $latex \[ ty [ i * (q + 1) + k ] = y_i^k \] $$ $head Examples$$ $subhead Define forward$$ The following files contain example atomic $code forward$$ functions: $cref%get_started.cpp%atomic_get_started.cpp%forward%$$, $cref%norm_sq.cpp%atomic_norm_sq.cpp%forward%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%forward%$$, $cref%tangent.cpp%atomic_tangent.cpp%forward%$$, $cref%matrix_mul.hpp%atomic_matrix_mul.hpp%forward%$$. $subhead Use forward$$ The following are links to user atomic function forward uses: $cref%get_started.cpp%atomic_get_started.cpp%Use Atomic Function%forward%$$, $cref%norm_sq.cpp%atomic_norm_sq.cpp%Use Atomic Function%forward%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%Use Atomic Function%forward%$$, $cref%tangent.cpp%atomic_tangent.cpp%Use Atomic Function%forward%$$, $cref%mat_mul.cpp%atomic_mat_mul.cpp%Use Atomic Function%forward%$$. $end ----------------------------------------------------------------------------- */ /*! Link from atomic_base to forward mode \param p [in] lowerest order for this forward mode calculation. \param q [in] highest order for this forward mode calculation. \param vx [in] if size not zero, which components of \c x are variables \param vy [out] if size not zero, which components of \c y are variables \param tx [in] Taylor coefficients corresponding to \c x for this calculation. \param ty [out] Taylor coefficient corresponding to \c y for this calculation See the forward mode in user's documentation for base_atomic */ virtual bool forward( size_t p , size_t q , const vector& vx , vector& vy , const vector& tx , vector& ty ) { return false; } /* ----------------------------------------------------------------------------- $begin atomic_reverse$$ $spell sq mul.hpp afun ty px py Taylor const CppAD $$ $section Atomic Reverse Mode$$ $index atomic, reverse callback$$ $index reverse, atomic callback$$ $index reverse, atomic virtual$$ $spell bool $$ $head Syntax$$ $icode%ok% = %afun%.reverse(%q%, %tx%, %ty%, %px%, %py%)%$$ $head Purpose$$ This function is used by $cref/reverse/Reverse/$$ to compute derivatives. $head Implementation$$ If you are using $cref/reverse/Reverse/$$ mode, this virtual function must be defined by the $cref/atomic_user/atomic_ctor/atomic_user/$$ class. It can just return $icode%ok% == false%$$ (and not compute anything) for values of $icode q$$ that are greater than those used by your $cref/reverse/Reverse/$$ mode calculations. $head q$$ The argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the highest order Taylor coefficient that computing the derivative of. $head tx$$ The argument $icode tx$$ has prototype $codei% const CppAD::vector<%Base%>& %tx% %$$ and $icode%tx%.size() == (%q%+1)*%n%$$. For $latex j = 0 , \ldots , n-1$$ and $latex k = 0 , \ldots , q$$, we use the Taylor coefficient notation $latex \[ \begin{array}{rcl} x_j^k & = & tx [ j * ( q + 1 ) + k ] \\ X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q \end{array} \] $$ Note that superscripts represent an index for $latex x_j^k$$ and an exponent for $latex t^k$$. Also note that the Taylor coefficients for $latex X(t)$$ correspond to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way: $latex \[ x_j^k = \frac{1}{ k ! } X_j^{(k)} (0) \] $$ $head ty$$ The argument $icode ty$$ has prototype $codei% const CppAD::vector<%Base%>& %ty% %$$ and $icode%tx%.size() == (%q%+1)*%m%$$. For $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , q$$, we use the Taylor coefficient notation $latex \[ \begin{array}{rcl} Y_i (t) & = & f_i [ X(t) ] \\ Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q ) \\ y_i^k & = & ty [ i * ( q + 1 ) + k ] \end{array} \] $$ where $latex o( t^q ) / t^q \rightarrow 0$$ as $latex t \rightarrow 0$$. Note that superscripts represent an index for $latex y_j^k$$ and an exponent for $latex t^k$$. Also note that the Taylor coefficients for $latex Y(t)$$ correspond to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way: $latex \[ y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0) \] $$ $head F, G, H$$ We use the notation $latex \{ x_j^k \} \in B^{n \times (q+1)}$$ for $latex \[ \{ x_j^k \W{:} j = 0 , \ldots , n-1, k = 0 , \ldots , q \} \]$$ We use the notation $latex \{ y_i^k \} \in B^{m \times (q+1)}$$ for $latex \[ \{ y_i^k \W{:} i = 0 , \ldots , m-1, k = 0 , \ldots , q \} \]$$ We define the function $latex F : B^{n \times (q+1)} \rightarrow B^{m \times (q+1)}$$ by $latex \[ y_i^k = F_i^k [ \{ x_j^k \} ] \] $$ We use $latex G : B^{m \times (q+1)} \rightarrow B$$ to denote an arbitrary scalar valued function of $latex \{ y_i^k \}$$. We use $latex H : B^{n \times (q+1)} \rightarrow B$$ defined by $latex \[ H ( \{ x_j^k \} ) = G[ F( \{ x_j^k \} ) ] \] $$ $head py$$ The argument $icode py$$ has prototype $codei% const CppAD::vector<%Base%>& %py% %$$ and $icode%py%.size() == m * (%q%+1)%$$. For $latex i = 0 , \ldots , m-1$$, $latex k = 0 , \ldots , q$$, $latex \[ py[ i * (q + 1 ) + k ] = \partial G / \partial y_i^k \] $$ $subhead px$$ The $icode px$$ has prototype $codei% CppAD::vector<%Base%>& %px% %$$ and $icode%px%.size() == n * (%q%+1)%$$. The input values of the elements of $icode px$$ are not specified (must not matter). Upon return, for $latex j = 0 , \ldots , n-1$$ and $latex \ell = 0 , \ldots , q$$, $latex \[ \begin{array}{rcl} px [ j * (q + 1) + \ell ] & = & \partial H / \partial x_j^\ell \\ & = & ( \partial G / \partial \{ y_i^k \} ) ( \partial \{ y_i^k \} / \partial x_j^\ell ) \\ & = & \sum_{i=0}^{m-1} \sum_{k=0}^q ( \partial G / \partial y_i^k ) ( \partial y_i^k / \partial x_j^\ell ) \\ & = & \sum_{i=0}^{m-1} \sum_{k=\ell}^q py[ i * (q + 1 ) + k ] ( \partial F_i^k / \partial x_j^\ell ) \end{array} \] $$ Note that we have used the fact that for $latex k < \ell$$, $latex \partial F_i^k / \partial x_j^\ell = 0$$. $head ok$$ The return value $icode ok$$ has prototype $codei% bool %ok% %$$ If it is $code true$$, the corresponding evaluation succeeded, otherwise it failed. $head Examples$$ $subhead Define reverse$$ The following files contain example atomic $code reverse$$ functions: $cref%norm_sq.cpp%atomic_norm_sq.cpp%reverse%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%reverse%$$, $cref%tangent.cpp%atomic_tangent.cpp%reverse%$$, $cref%matrix_mul.hpp%atomic_matrix_mul.hpp%reverse%$$. $subhead Use reverse$$ The following are links to user atomic function constructor uses: $cref%norm_sq.cpp%atomic_norm_sq.cpp%Use Atomic Function%reverse%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%Use Atomic Function%reverse%$$, $cref%tangent.cpp%atomic_tangent.cpp%Use Atomic Function%reverse%$$, $cref%mat_mul.cpp%atomic_mat_mul.cpp%Use Atomic Function%reverse%$$. $end ----------------------------------------------------------------------------- */ /*! Link from reverse mode sweep to users routine. \param q [in] highest order for this reverse mode calculation. \param tx [in] Taylor coefficients corresponding to \c x for this calculation. \param ty [in] Taylor coefficient corresponding to \c y for this calculation \param px [out] Partials w.r.t. the \c x Taylor coefficients. \param py [in] Partials w.r.t. the \c y Taylor coefficients. See atomic_reverse mode use documentation */ virtual bool reverse( size_t q , const vector& tx , const vector& ty , vector& px , const vector& py ) { return false; } /* -------------------------------------- --------------------------------------- $begin atomic_for_sparse_jac$$ $spell sq mul.hpp afun Jacobian jac const CppAD std bool std $$ $section Atomic Forward Jacobian Sparsity Patterns$$ $index atomic, for_sparse_jac callback$$ $index for_sparse_jac, atomic callback$$ $index for_sparse_jac, atomic virtual$$ $head Syntax$$ $icode%ok% = %afun%.for_sparse_jac(%q%, %r%, %s%)%$$ $head Purpose$$ This function is used by $cref ForSparseJac$$ to compute Jacobian sparsity patterns. For a fixed matrix $latex R \in B^{n \times q}$$, the Jacobian of $latex f( x + R * u)$$ with respect to $latex u \in B^q$$ is $latex \[ S(x) = f^{(1)} (x) * R \] $$ Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$, $code for_sparse_jac$$ computes a sparsity pattern for $latex S(x)$$. $head Implementation$$ If you are using $cref ForSparseJac$$, this virtual function must be defined by the $cref/atomic_user/atomic_ctor/atomic_user/$$ class. $subhead q$$ The argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of columns in $latex R \in B^{n \times q}$$ and the Jacobian $latex S(x) \in B^{m \times q}$$. $subhead r$$ This argument has prototype $codei% const %atomic_sparsity%& %r% %$$ and is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for $latex R \in B^{n \times q}$$. $subhead s$$ This argument has prototype $codei% %atomic_sparsity%& %s% %$$ The input values of its elements are not specified (must not matter). Upon return, $icode s$$ is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for $latex S(x) \in B^{m \times q}$$. $head ok$$ The return value $icode ok$$ has prototype $codei% bool %ok% %$$ If it is $code true$$, the corresponding evaluation succeeded, otherwise it failed. $head Examples$$ $subhead Define for_sparse_jac$$ The following files contain example atomic $code for_sparse_jac$$ functions: $cref%norm_sq.cpp%atomic_norm_sq.cpp%for_sparse_jac%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%for_sparse_jac%$$, $cref%tangent.cpp%atomic_tangent.cpp%for_sparse_jac%$$, $cref%matrix_mul.hpp%atomic_matrix_mul.hpp%for_sparse_jac%$$. $subhead Use for_sparse_jac$$ The following are links to user atomic function constructor uses: $cref%norm_sq.cpp% atomic_norm_sq.cpp%Use Atomic Function%for_sparse_jac%$$, $cref%reciprocal.cpp% atomic_reciprocal.cpp%Use Atomic Function%for_sparse_jac%$$, $cref%tangent.cpp%atomic_tangent.cpp%Use Atomic Function%for_sparse_jac%$$, $cref%mat_mul.cpp%atomic_mat_mul.cpp%Use Atomic Function%for_sparse_jac%$$. $end ----------------------------------------------------------------------------- */ /*! Link from forward Jacobian sparsity sweep to atomic_base \param q is the column dimension for the Jacobian sparsity partterns. \param r is the Jacobian sparsity pattern for the argument vector x \param s is the Jacobian sparsity pattern for the result vector y */ virtual bool for_sparse_jac( size_t q , const vector< std::set >& r , vector< std::set >& s ) { return false; } virtual bool for_sparse_jac( size_t q , const vector& r , vector& s ) { return false; } /* -------------------------------------- --------------------------------------- $begin atomic_rev_sparse_jac$$ $spell sq mul.hpp rt afun Jacobian jac CppAD std bool const hes $$ $section Atomic Reverse Jacobian Sparsity Patterns$$ $index atomic, rev_sparse_jac callback$$ $index rev_sparse_jac, atomic callback$$ $index rev_sparse_jac, atomic virtual$$ $head Syntax$$ $icode%ok% = %afun%.rev_sparse_jac(%q%, %rt%, %st%)%$$ $head Purpose$$ This function is used by $cref RevSparseJac$$ to compute Jacobian sparsity patterns. For a fixed matrix $latex R \in B^{q \times m}$$, the Jacobian of $latex R * f( x )$$ with respect to $latex x \in B^q$$ is $latex \[ S(x) = R * f^{(1)} (x) \] $$ Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$, $code rev_sparse_jac$$ computes a sparsity pattern for $latex S(x)$$. $head Implementation$$ If you are using $cref RevSparseJac$$, this virtual function must be defined by the $cref/atomic_user/atomic_ctor/atomic_user/$$ class. $subhead q$$ The argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of rows in $latex R \in B^{q \times m}$$ and the Jacobian $latex S(x) \in B^{q \times n}$$. $subhead rt$$ This argument has prototype $codei% const %atomic_sparsity%& %rt% %$$ and is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for $latex R^\R{T} \in B^{m \times q}$$. $subhead st$$ This argument has prototype $codei% %atomic_sparsity%& %st% %$$ The input value of its elements are not specified (must not matter). Upon return, $icode s$$ is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for $latex S(x)^\R{T} \in B^{n \times q}$$. $head ok$$ The return value $icode ok$$ has prototype $codei% bool %ok% %$$ If it is $code true$$, the corresponding evaluation succeeded, otherwise it failed. $head Examples$$ $subhead Define rev_sparse_jac$$ The following files contain example atomic $code rev_sparse_jac$$ functions: $cref%norm_sq.cpp%atomic_norm_sq.cpp%rev_sparse_jac%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%rev_sparse_jac%$$, $cref%tangent.cpp%atomic_tangent.cpp%rev_sparse_jac%$$, $cref%matrix_mul.hpp%atomic_matrix_mul.hpp%rev_sparse_jac%$$. $subhead Use rev_sparse_jac$$ The following are links to user atomic function constructor uses: $cref%norm_sq.cpp% atomic_norm_sq.cpp%Use Atomic Function%rev_sparse_jac%$$, $cref%reciprocal.cpp% atomic_reciprocal.cpp%Use Atomic Function%rev_sparse_jac%$$, $cref%tangent.cpp%atomic_tangent.cpp%Use Atomic Function%rev_sparse_jac%$$, $cref%mat_mul.cpp%atomic_mat_mul.cpp%Use Atomic Function%rev_sparse_jac%$$. $end ----------------------------------------------------------------------------- */ /*! Link from reverse Jacobian sparsity sweep to atomic_base \param q [in] is the row dimension for the Jacobian sparsity partterns \param rt [out] is the tansposed Jacobian sparsity pattern w.r.t to range variables y \param st [in] is the tansposed Jacobian sparsity pattern for the argument variables x */ virtual bool rev_sparse_jac( size_t q , const vector< std::set >& rt , vector< std::set >& st ) { return false; } virtual bool rev_sparse_jac( size_t q , const vector& rt , vector& st ) { return false; } /* -------------------------------------- --------------------------------------- $begin atomic_rev_sparse_hes$$ $spell sq mul.hpp vx afun Jacobian jac CppAD std bool hes const $$ $section Atomic Reverse Hessian Sparsity Patterns$$ $index atomic, rev_sparse_hes callback$$ $index rev_sparse_hes, atomic callback$$ $index rev_sparse_hes, atomic virtual$$ $head Syntax$$ $icode%ok% = %afun%.rev_sparse_hes(%vx%, %s%, %t%, %q%, %r%, %u%, %v%)%$$ $head Purpose$$ This function is used by $cref RevSparseHes$$ to compute Hessian sparsity patterns. There is an unspecified scalar valued function $latex g : B^m \rightarrow B$$. Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R \in B^{n \times q}$$, and information about the function $latex z = g(y)$$, this routine computes the sparsity pattern for $latex \[ V(x) = (g \circ f)^{(2)}( x ) R \] $$ $head Implementation$$ If you are using and $cref RevSparseHes$$, this virtual function must be defined by the $cref/atomic_user/atomic_ctor/atomic_user/$$ class. $subhead vx$$ The argument $icode vx$$ has prototype $codei% const CppAD:vector& %vx% %$$ $icode%vx%.size() == %n%$$, and for $latex j = 0 , \ldots , n-1$$, $icode%vx%[%j%]%$$ is true if and only if $icode%ax%[%j%]%$$ is a $cref/variable/glossary/Variable/$$ in the corresponding call to $codei% %afun%(%ax%, %ay%, %id%) %$$ $subhead s$$ The argument $icode s$$ has prototype $codei% const CppAD:vector& %s% %$$ and its size is $icode m$$. It is a sparsity pattern for $latex S(x) = g^{(1)} (y) \in B^{1 \times m}$$. $subhead t$$ This argument has prototype $codei% CppAD:vector& %t% %$$ and its size is $icode m$$. The input values of its elements are not specified (must not matter). Upon return, $icode t$$ is a sparsity pattern for $latex T(x) \in B^{1 \times n}$$ where $latex \[ T(x) = (g \circ f)^{(1)} (x) = S(x) * f^{(1)} (x) \]$$ $subhead q$$ The argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of columns in $latex R \in B^{n \times q}$$, $latex U(x) \in B^{m \times q}$$, and $latex V(x) \in B^{n \times q}$$. $subhead r$$ This argument has prototype $codei% const %atomic_sparsity%& %r% %$$ and is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for $latex R \in B^{n \times q}$$. $head u$$ This argument has prototype $codei% const %atomic_sparsity%& %u% %$$ and is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for $latex U(x) \in B^{m \times q}$$ which is defined by $latex \[ \begin{array}{rcl} U(x) & = & \partial_u \{ \partial_y g[ y + f^{(1)} (x) R u ] \}_{u=0} \\ & = & \partial_u \{ g^{(1)} [ y + f^{(1)} (x) R u ] \}_{u=0} \\ & = & g^{(2)} (y) f^{(1)} (x) R \end{array} \] $$ $subhead v$$ This argument has prototype $codei% %atomic_sparsity%& %v% %$$ The input value of its elements are not specified (must not matter). Upon return, $icode v$$ is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for $latex V(x) \in B^{n \times q}$$ which is defined by $latex \[ \begin{array}{rcl} V(x) & = & \partial_u [ \partial_x (g \circ f) ( x + R u ) ]_{u=0} \\ & = & \partial_u [ (g \circ f)^{(1)}( x + R u ) ]_{u=0} \\ & = & (g \circ f)^{(2)}( x ) R \\ & = & f^{(1)} (x)^\R{T} g^{(2)} ( y ) f^{(1)} (x) R + \sum_{i=1}^m g_i^{(1)} (y) \; f_i^{(2)} (x) R \\ & = & f^{(1)} (x)^\R{T} U(x) + \sum_{i=1}^m S_i (x) \; f_i^{(2)} (x) R \end{array} \] $$ $head Examples$$ $subhead Define rev_sparse_hes$$ The following files contain example atomic $code rev_sparse_hes$$ functions: $cref%norm_sq.cpp%atomic_norm_sq.cpp%rev_sparse_hes%$$, $cref%reciprocal.cpp%atomic_reciprocal.cpp%rev_sparse_hes%$$, $cref%tangent.cpp%atomic_tangent.cpp%rev_sparse_hes%$$, $cref%matrix_mul.hpp%atomic_matrix_mul.hpp%rev_sparse_hes%$$. $subhead Use rev_sparse_hes$$ The following are links to user atomic function constructor uses: $cref%norm_sq.cpp% atomic_norm_sq.cpp%Use Atomic Function%rev_sparse_hes%$$, $cref%reciprocal.cpp% atomic_reciprocal.cpp%Use Atomic Function%rev_sparse_hes%$$, $cref%tangent.cpp%atomic_tangent.cpp%Use Atomic Function%rev_sparse_hes%$$, $cref%mat_mul.cpp%atomic_mat_mul.cpp%Use Atomic Function%rev_sparse_hes%$$. $end ----------------------------------------------------------------------------- */ /*! Link from reverse Hessian sparsity sweep to base_atomic \param vx [in] which componens of x are variables. \param s [in] is the reverse Jacobian sparsity pattern w.r.t the result vector y. \param t [out] is the reverse Jacobian sparsity pattern w.r.t the argument vector x. \param q [in] is the column dimension for the sparsity partterns. \param r [in] is the forward Jacobian sparsity pattern w.r.t the argument vector x \param u [in] is the Hessian sparsity pattern w.r.t the result vector y. \param v [out] is the Hessian sparsity pattern w.r.t the argument vector x. */ virtual bool rev_sparse_hes( const vector& vx , const vector& s , vector& t , size_t q , const vector< std::set >& r , const vector< std::set >& u , vector< std::set >& v ) { return false; } virtual bool rev_sparse_hes( const vector& vx , const vector& s , vector& t , size_t q , const vector& r , const vector& u , vector& v ) { return false; } /* ------------------------------------------------------------------------------ $begin atomic_base_clear$$ $spell sq alloc $$ $section Free Static Variables$$ $index free, atomic static$$ $index atomic, free static$$ $index static, free atomic$$ $index clear, atomic static$$ $head Syntax$$ $codei%atomic_base<%Base%>::clear()%$$ $head Purpose$$ Each $code atomic_base$$ objects holds onto work space in order to avoid repeated memory allocation calls and thereby increase speed (until it is deleted). If an the $code atomic_base$$ object is global or static because, the it does not get deleted. This is a problem when using $code thread_alloc$$ $cref/free_all/ta_free_all/$$ to check that all allocated memory has been freed. Calling this $code clear$$ function will free all the memory currently being held onto by the $codei%atomic_base<%Base%>%$$ class. $head Future Use$$ If there is future use of an $code atomic_base$$ object, after a call to $code clear$$, the work space will be reallocated and held onto. $head Restriction$$ This routine cannot be called while in $cref/parallel/ta_in_parallel/$$ execution mode. $end ------------------------------------------------------------------------------ */ /*! Free all thread_alloc static memory held by atomic_base (avoids reallocations). (This does not include class_object() which is an std::vector.) */ /// Free vector memory used by this class (work space) static void clear(void) { CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "cannot use atomic_base clear during parallel execution" ); size_t i = class_object().size(); while(i--) { size_t thread = CPPAD_MAX_NUM_THREADS; while(thread--) { atomic_base* op = class_object()[i]; if( op != CPPAD_NULL ) { op->afun_vx_[thread].clear(); op->afun_vy_[thread].clear(); op->afun_tx_[thread].clear(); op->afun_ty_[thread].clear(); } } } return; } // ------------------------------------------------------------------------- /*! Set value of id (used by deprecated old_atomic class) This function is called just before calling any of the virtual funcitons and has the corresponding id of the corresponding virtual call. */ virtual void set_id(size_t id) { } // --------------------------------------------------------------------------- }; } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sparse.hpp0000644000176200001440000000175514536067013017500 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_INCLUDED # define CPPAD_SPARSE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-06 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Sparse$$ $spell $$ $index sparsity, pattern$$ $index pattern, sparsity$$ $section Calculating Sparsity Patterns$$ $childtable% cppad/local/for_sparse_jac.hpp% cppad/local/rev_sparse_jac.hpp% cppad/local/rev_sparse_hes.hpp %$$ $end */ # include # include # include # endif TMB/inst/include/cppad/local/sparse_unary_op.hpp0000644000176200001440000001255414536067013021413 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_UNARY_OP_INCLUDED # define CPPAD_SPARSE_UNARY_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sparse_unary_op.hpp Forward and reverse mode sparsity patterns for unary operators. */ /*! Forward mode Jacobian sparsity pattern for all unary operators. The C++ source code corresponding to a unary operation has the form \verbatim z = fun(x) \endverbatim where fun is a C++ unary function, or it has the form \verbatim z = x op q \endverbatim where op is a C++ binary unary operator and q is a parameter. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e., z. \param i_x variable index corresponding to the argument for this operator; i.e., x. \param sparsity \b Input: The set with index \a arg[0] in \a sparsity is the sparsity bit pattern for x. This identifies which of the independent variables the variable x depends on. \n \n \b Output: The set with index \a i_z in \a sparsity is the sparsity bit pattern for z. This identifies which of the independent variables the variable z depends on. \n \par Checked Assertions: \li \a i_x < \a i_z */ template inline void forward_sparse_jacobian_unary_op( size_t i_z , size_t i_x , Vector_set& sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( i_x < i_z ); sparsity.assignment(i_z, i_x, sparsity); } /*! Reverse mode Jacobian sparsity pattern for all unary operators. The C++ source code corresponding to a unary operation has the form \verbatim z = fun(x) \endverbatim where fun is a C++ unary function, or it has the form \verbatim z = x op q \endverbatim where op is a C++ bianry operator and q is a parameter. This routine is given the sparsity patterns for a function G(z, y, ... ) and it uses them to compute the sparsity patterns for \verbatim H( x , w , u , ... ) = G[ z(x) , x , w , u , ... ] \endverbatim \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e. the row index in sparsity corresponding to z. \param i_x variable index corresponding to the argument for this operator; i.e. the row index in sparsity corresponding to x. \param sparsity \b Input: The set with index \a i_z in \a sparsity is the sparsity bit pattern for G with respect to the variable z. \n \b Input: The set with index \a i_x in \a sparsity is the sparsity bit pattern for G with respect to the variable x. \n \b Output: The set with index \a i_x in \a sparsity is the sparsity bit pattern for H with respect to the variable x. \par Checked Assertions: \li \a i_x < \a i_z */ template inline void reverse_sparse_jacobian_unary_op( size_t i_z , size_t i_x , Vector_set& sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( i_x < i_z ); sparsity.binary_union(i_x, i_x, i_z, sparsity); return; } /*! Reverse mode Hessian sparsity pattern for linear unary operators. The C++ source code corresponding to this operation is \verbatim z = fun(x) \endverbatim where fun is a linear functions; e.g. abs, or \verbatim z = x op q \endverbatim where op is a C++ binary operator and q is a parameter. \copydetails reverse_sparse_hessian_unary_op */ template inline void reverse_sparse_hessian_linear_unary_op( size_t i_z , size_t i_x , bool* rev_jacobian , Vector_set& for_jac_sparsity , Vector_set& rev_hes_sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( i_x < i_z ); rev_hes_sparsity.binary_union(i_x, i_x, i_z, rev_hes_sparsity); rev_jacobian[i_x] |= rev_jacobian[i_z]; return; } /*! Reverse mode Hessian sparsity pattern for non-linear unary operators. The C++ source code corresponding to this operation is \verbatim z = fun(x) \endverbatim where fun is a non-linear functions; e.g. sin. or \verbatim z = q / x \endverbatim where q is a parameter. \copydetails reverse_sparse_hessian_unary_op */ template inline void reverse_sparse_hessian_nonlinear_unary_op( size_t i_z , size_t i_x , bool* rev_jacobian , Vector_set& for_jac_sparsity , Vector_set& rev_hes_sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( i_x < i_z ); rev_hes_sparsity.binary_union(i_x, i_x, i_z, rev_hes_sparsity); if( rev_jacobian[i_z] ) rev_hes_sparsity.binary_union(i_x, i_x, i_x, for_jac_sparsity); rev_jacobian[i_x] |= rev_jacobian[i_z]; return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/compute_assign.hpp0000644000176200001440000000751114536067013021217 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_COMPUTE_ASSIGN_INCLUDED # define CPPAD_COMPUTE_ASSIGN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin compute_assign$$ $spell Op VecAD const $$ $section AD Computed Assignment Operators$$ $index assignment, operator$$ $index operator, assignment$$ $index +, computed assignment$$ $index add, computed assignment$$ $index plus, computed assignment$$ $index -, computed assignment$$ $index subtract, computed assignment$$ $index minus, computed assignment$$ $index *, computed assignment$$ $index multiply, computed assignment$$ $index times, computed assignment$$ $index /, computed assignment$$ $index divide, computed assignment$$ $head Syntax$$ $icode%x% %Op% %y%$$ $head Purpose$$ Performs computed assignment operations where either $icode x$$ has type $codei%AD<%Base%>%$$. $head Op$$ The operator $icode Op$$ is one of the following $table $bold Op$$ $cnext $bold Meaning$$ $rnext $code +=$$ $cnext $icode x$$ is assigned $icode x$$ plus $icode y$$ $rnext $code -=$$ $cnext $icode x$$ is assigned $icode x$$ minus $icode y$$ $rnext $code *=$$ $cnext $icode x$$ is assigned $icode x$$ times $icode y$$ $rnext $code /=$$ $cnext $icode x$$ is assigned $icode x$$ divided by $icode y$$ $tend $head Base$$ The type $icode Base$$ is determined by the operand $icode x$$. $head x$$ The operand $icode x$$ has the following prototype $codei% AD<%Base%> &%x% %$$ $head y$$ The operand $icode y$$ has the following prototype $codei% const %Type% &%y% %$$ where $icode Type$$ is $codei%VecAD<%Base%>::reference%$$, $codei%AD<%Base%>%$$, $icode Base$$, or $code double$$. $head Result$$ $index assignment, multiple$$ $index multiple, assignment$$ The result of this assignment can be used as a reference to $icode x$$. For example, if $icode z$$ has the following type $codei% AD<%Base%> %z% %$$ then the syntax $codei% %z% = %x% += %y% %$$ will compute $icode x$$ plus $icode y$$ and then assign this value to both $icode x$$ and $icode z$$. $head Operation Sequence$$ This is an $cref/atomic/glossary/Operation/Atomic/$$ $cref/AD of Base/glossary/AD of Base/$$ operation and hence it is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $children% example/add_eq.cpp% example/sub_eq.cpp% example/mul_eq.cpp% example/div_eq.cpp %$$ $head Example$$ The following files contain examples and tests of these functions. Each test returns true if it succeeds and false otherwise. $table $rref AddEq.cpp$$ $rref sub_eq.cpp$$ $rref mul_eq.cpp$$ $rref div_eq.cpp$$ $tend $head Derivative$$ If $latex f$$ and $latex g$$ are $cref/Base functions/glossary/Base Function/$$ $subhead Addition$$ $latex \[ \D{[ f(x) + g(x) ]}{x} = \D{f(x)}{x} + \D{g(x)}{x} \] $$ $subhead Subtraction$$ $latex \[ \D{[ f(x) - g(x) ]}{x} = \D{f(x)}{x} - \D{g(x)}{x} \] $$ $subhead Multiplication$$ $latex \[ \D{[ f(x) * g(x) ]}{x} = g(x) * \D{f(x)}{x} + f(x) * \D{g(x)}{x} \] $$ $subhead Division$$ $latex \[ \D{[ f(x) / g(x) ]}{x} = [1/g(x)] * \D{f(x)}{x} - [f(x)/g(x)^2] * \D{g(x)}{x} \] $$ $end ----------------------------------------------------------------------------- */ # include # include # include # include # endif TMB/inst/include/cppad/local/arithmetic.hpp0000644000176200001440000000257314536067013020333 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ARITHMETIC_INCLUDED # define CPPAD_ARITHMETIC_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-07 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin Arithmetic$$ $spell Op const $$ $index operator, AD arithmetic$$ $index AD, arithmetic operator$$ $index arithmetic, AD operator$$ $index computed, AD assignment$$ $index assignment, AD computed$$ $index AD, computed assignment$$ $section AD Arithmetic Operators and Computed Assignments$$ $childtable% cppad/local/unary_plus.hpp% cppad/local/unary_minus.hpp% cppad/local/ad_binary.hpp% cppad/local/compute_assign.hpp %$$ $end ------------------------------------------------------------------------------- */ # include # include # include # include # endif TMB/inst/include/cppad/local/base_double.hpp0000644000176200001440000001240414536067013020440 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BASE_DOUBLE_INCLUDED # define CPPAD_BASE_DOUBLE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include /* $begin base_double.hpp$$ $spell erf endif abs_geq acos asin atan cos sqrt tanh std fabs bool Lt Le Eq Ge Gt Rel CppAD CondExpOp namespace inline enum const exp const $$ $index double, Base$$ $index Base, double$$ $index double, Base$$ $section Enable use of AD where Base is double$$ $head CondExpOp$$ The type $code double$$ is a relatively simple type that supports $code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators; see $cref/ordered type/base_cond_exp/CondExpTemplate/Ordered Type/$$. Hence its $code CondExpOp$$ function is defined by $codep */ namespace CppAD { inline double CondExpOp( enum CompareOp cop , const double& left , const double& right , const double& exp_if_true , const double& exp_if_false ) { return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false); } } /* $$ $head CondExpRel$$ The $cref/CPPAD_COND_EXP_REL/base_cond_exp/CondExpRel/$$ macro invocation $codep */ namespace CppAD { CPPAD_COND_EXP_REL(double) } /* $$ uses $code CondExpOp$$ above to define $codei%CondExp%Rel%$$ for $code double$$ arguments and $icode%Rel%$$ equal to $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, and $code Gt$$. $head EqualOpSeq$$ The type $code double$$ is simple (in this respect) and so we define $codep */ namespace CppAD { inline bool EqualOpSeq(const double& x, const double& y) { return x == y; } } /* $$ $head Identical$$ The type $code double$$ is simple (in this respect) and so we define $codep */ namespace CppAD { inline bool IdenticalPar(const double& x) { return true; } inline bool IdenticalZero(const double& x) { return (x == 0.); } inline bool IdenticalOne(const double& x) { return (x == 1.); } inline bool IdenticalEqualPar(const double& x, const double& y) { return (x == y); } } /* $$ $head Integer$$ $codep */ namespace CppAD { inline int Integer(const double& x) { return static_cast(x); } } /* $$ $head Ordered$$ The $code double$$ type supports ordered comparisons $codep */ namespace CppAD { inline bool GreaterThanZero(const double& x) { return x > 0.; } inline bool GreaterThanOrZero(const double& x) { return x >= 0.; } inline bool LessThanZero(const double& x) { return x < 0.; } inline bool LessThanOrZero(const double& x) { return x <= 0.; } inline bool abs_geq(const double& x, const double& y) { return std::fabs(x) >= std::fabs(y); } } /* $$ $head Unary Standard Math$$ The following macro invocations define the unary standard math functions required to use $code AD$$: $codep */ namespace CppAD { CPPAD_STANDARD_MATH_UNARY(double, acos) CPPAD_STANDARD_MATH_UNARY(double, asin) CPPAD_STANDARD_MATH_UNARY(double, atan) CPPAD_STANDARD_MATH_UNARY(double, cos) CPPAD_STANDARD_MATH_UNARY(double, cosh) CPPAD_STANDARD_MATH_UNARY(double, exp) CPPAD_STANDARD_MATH_UNARY(double, fabs) CPPAD_STANDARD_MATH_UNARY(double, log) CPPAD_STANDARD_MATH_UNARY(double, log10) CPPAD_STANDARD_MATH_UNARY(double, sin) CPPAD_STANDARD_MATH_UNARY(double, sinh) CPPAD_STANDARD_MATH_UNARY(double, sqrt) CPPAD_STANDARD_MATH_UNARY(double, tan) CPPAD_STANDARD_MATH_UNARY(double, tanh) # if CPPAD_COMPILER_HAS_ERF CPPAD_STANDARD_MATH_UNARY(double, erf) # endif } /* $$ The absolute value function is special because its $code std$$ name is $code fabs$$ $codep */ namespace CppAD { inline double abs(const double& x) { return std::fabs(x); } } /* $$ $head sign$$ The following defines the $code CppAD::sign$$ function that is required to use $code AD$$: $codep */ namespace CppAD { inline double sign(const double& x) { if( x > 0. ) return 1.; if( x == 0. ) return 0.; return -1.; } } /* $$ $head pow $$ The following defines a $code CppAD::pow$$ function that is required to use $code AD$$: $codep */ namespace CppAD { inline double pow(const double& x, const double& y) { return std::pow(x, y); } } /*$$ $head limits$$ The following defines the numeric limits functions $code epsilon$$, $code min$$, and $code max$$ for the type $code double$$. It also defines the deprecated $code epsilon$$ function: $codep */ namespace CppAD { template <> class numeric_limits { public: // machine epsilon static double epsilon(void) { return std::numeric_limits::epsilon(); } // minimum positive normalized value static double min(void) { return std::numeric_limits::min(); } // maximum finite value static double max(void) { return std::numeric_limits::max(); } }; // deprecated machine epsilon template <> inline double epsilon(void) { return numeric_limits::epsilon(); } } /* $$ $end */ # endif TMB/inst/include/cppad/local/div_op.hpp0000644000176200001440000003607714536067013017470 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DIV_OP_INCLUDED # define CPPAD_DIV_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file div_op.hpp Forward and reverse mode calculations for z = x / y. */ // --------------------------- Divvv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = DivvvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op */ template inline void forward_divvv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; // Using CondExp, it can make sense to divide by zero, // so do not make it an error. size_t k; for(size_t d = p; d <= q; d++) { z[d] = x[d]; for(k = 1; k <= d; k++) z[d] -= z[d-k] * y[k]; z[d] /= y[0]; } } /*! Multiple directions forward mode Taylor coefficients for op = DivvvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op_dir */ template inline void forward_divvv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + arg[0] * num_taylor_per_var; Base* y = taylor + arg[1] * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; // Using CondExp, it can make sense to divide by zero, // so do not make it an error. size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { z[m+ell] = x[m+ell] - z[0] * y[m+ell]; for(size_t k = 1; k < q; k++) z[m+ell] -= z[(q-k-1)*r+1+ell] * y[(k-1)*r+1+ell]; z[m+ell] /= y[0]; } } /*! Compute zero order forward mode Taylor coefficients for result of op = DivvvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op_0 */ template inline void forward_divvv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x[0] / y[0]; } /*! Compute reverse mode partial derivatives for result of op = DivvvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails reverse_binary_op */ template inline void reverse_divvv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Arguments const Base* y = taylor + arg[1] * cap_order; const Base* z = taylor + i_z * cap_order; // Partial derivatives corresponding to arguments and result Base* px = partial + arg[0] * nc_partial; Base* py = partial + arg[1] * nc_partial; Base* pz = partial + i_z * nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; // Using CondExp, it can make sense to divide by zero // so do not make it an error. size_t k; // number of indices to access size_t j = d + 1; while(j) { --j; // scale partial w.r.t. z[j] pz[j] /= y[0]; px[j] += pz[j]; for(k = 1; k <= j; k++) { pz[j-k] -= pz[j] * y[k]; py[k] -= pz[j] * z[j-k]; } py[0] -= pz[j] * z[j]; } } // --------------------------- Divpv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = DivpvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op */ template inline void forward_divpv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; // Paraemter value Base x = parameter[ arg[0] ]; // Using CondExp, it can make sense to divide by zero, // so do not make it an error. size_t k; if( p == 0 ) { z[0] = x / y[0]; p++; } for(size_t d = p; d <= q; d++) { z[d] = Base(0); for(k = 1; k <= d; k++) z[d] -= z[d-k] * y[k]; z[d] /= y[0]; } } /*! Multiple directions forward mode Taylor coefficients for op = DivpvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op_dir */ template inline void forward_divpv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* y = taylor + arg[1] * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; // Using CondExp, it can make sense to divide by zero, // so do not make it an error. size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { z[m+ell] = - z[0] * y[m+ell]; for(size_t k = 1; k < q; k++) z[m+ell] -= z[(q-k-1)*r+1+ell] * y[(k-1)*r+1+ell]; z[m+ell] /= y[0]; } } /*! Compute zero order forward mode Taylor coefficient for result of op = DivpvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op_0 */ template inline void forward_divpv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 ); // Paraemter value Base x = parameter[ arg[0] ]; // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x / y[0]; } /*! Compute reverse mode partial derivative for result of op = DivpvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails reverse_binary_op */ template inline void reverse_divpv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Arguments const Base* y = taylor + arg[1] * cap_order; const Base* z = taylor + i_z * cap_order; // Partial derivatives corresponding to arguments and result Base* py = partial + arg[1] * nc_partial; Base* pz = partial + i_z * nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; // Using CondExp, it can make sense to divide by zero so do not // make it an error. size_t k; // number of indices to access size_t j = d + 1; while(j) { --j; // scale partial w.r.t z[j] pz[j] /= y[0]; for(k = 1; k <= j; k++) { pz[j-k] -= pz[j] * y[k]; py[k] -= pz[j] * z[j-k]; } py[0] -= pz[j] * z[j]; } } // --------------------------- Divvp ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = DivvvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_binary_op */ template inline void forward_divvp_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* z = taylor + i_z * cap_order; // Parameter value Base y = parameter[ arg[1] ]; // Using CondExp and multiple levels of AD, it can make sense // to divide by zero so do not make it an error. for(size_t d = p; d <= q; d++) z[d] = x[d] / y; } /*! Multiple direction forward mode Taylor coefficients for op = DivvvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_binary_op_dir */ template inline void forward_divvp_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( 0 < q ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + arg[0] * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; // Parameter value Base y = parameter[ arg[1] ]; // Using CondExp and multiple levels of AD, it can make sense // to divide by zero so do not make it an error. size_t m = (q-1)*r + 1; for(size_t ell = 0; ell < r; ell++) z[m + ell] = x[m + ell] / y; } /*! Compute zero order forward mode Taylor coefficients for result of op = DivvvOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_binary_op_0 */ template inline void forward_divvp_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); // Parameter value Base y = parameter[ arg[1] ]; // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x[0] / y; } /*! Compute reverse mode partial derivative for result of op = DivvpOp. The C++ source code corresponding to this operation is \verbatim z = x / y \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails reverse_binary_op */ template inline void reverse_divvp_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Argument values Base y = parameter[ arg[1] ]; // Partial derivatives corresponding to arguments and result Base* px = partial + arg[0] * nc_partial; Base* pz = partial + i_z * nc_partial; // Using CondExp, it can make sense to divide by zero // so do not make it an error. // number of indices to access size_t j = d + 1; while(j) { --j; px[j] += pz[j] / y; } } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/prototype_op.hpp0000644000176200001440000012452514536067013020747 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_PROTOTYPE_OP_INCLUDED # define CPPAD_PROTOTYPE_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file prototype_op.hpp Documentation for generic cases (these generic cases are never used). */ // ==================== Unary operators with one result ==================== /*! Prototype for forward mode unary operator with one result (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param p lowest order of the Taylor coefficient that we are computing. \param q highest order of the Taylor coefficient that we are computing. \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param i_x variable index corresponding to the argument for this operator; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: taylor [ i_x * cap_order + k ], for k = 0 , ... , q, is the k-th order Taylor coefficient corresponding to x. \n \b Input: taylor [ i_z * cap_order + k ], for k = 0 , ... , p-1, is the k-th order Taylor coefficient corresponding to z. \n \b Output: taylor [ i_z * cap_order + k ], for k = p , ... , q, is the k-th order Taylor coefficient corresponding to z. \par Checked Assertions \li NumArg(op) == 1 \li NumRes(op) == 1 \li q < cap_order \li p <= q */ template inline void forward_unary1_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for multiple direction forward mode unary operator with one result (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param q order of the Taylor coefficients that we are computing. \param r number of directions for Taylor coefficients that we are computing. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. The auxillary result is called y has index \a i_z - 1. \param i_x variable index corresponding to the argument for this operator; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the \c taylor array. \par tpv We use the notation tpv = (cap_order-1) * r + 1 which is the number of Taylor coefficients per variable \param taylor \b Input: If x is a variable, taylor [ arg[0] * tpv + 0 ], is the zero order Taylor coefficient for all directions and taylor [ arg[0] * tpv + (k-1)*r + ell + 1 ], for k = 1 , ... , q, ell = 0, ..., r-1, is the k-th order Taylor coefficient corresponding to x and the ell-th direction. \n \b Input: taylor [ i_z * tpv + 0 ], is the zero order Taylor coefficient for all directions and taylor [ i_z * tpv + (k-1)*r + ell + 1 ], for k = 1 , ... , q-1, ell = 0, ..., r-1, is the k-th order Taylor coefficient corresponding to z and the ell-th direction. \n \b Output: taylor [ i_z * tpv + (q-1)*r + ell + 1], ell = 0, ..., r-1, is the q-th order Taylor coefficient corresponding to z and the ell-th direction. \par Checked Assertions \li NumArg(op) == 1 \li NumRes(op) == 2 \li i_x < i_z \li 0 < q \li q < cap_order */ template inline void forward_unary1_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for zero order forward mode unary operator with one result (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param i_x variable index corresponding to the argument for this operator; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: \a taylor [ \a i_x * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to x. \n \b Output: \a taylor [ \a i_z * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to z. \par Checked Assertions \li NumArg(op) == 1 \li NumRes(op) == 1 \li \a i_x < \a i_z \li \a 0 < \a cap_order */ template inline void forward_unary1_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for reverse mode unary operator with one result (not used). This routine is given the partial derivatives of a function G(z , x , w, u ... ) and it uses them to compute the partial derivatives of \verbatim H( x , w , u , ... ) = G[ z(x) , x , w , u , ... ] \endverbatim \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param d highest order Taylor coefficient that we are computing the partial derivatives with respect to. \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor to z. \param i_x variable index corresponding to the argument for this operation; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \a taylor [ \a i_x * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to x. \n \a taylor [ \a i_z * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to z. \param nc_partial number of colums in the matrix containing all the partial derivatives. \param partial \b Input: \a partial [ \a i_x * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Input: \a partial [ \a i_z * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , x , w , u , ... ) with respect to the k-th order Taylor coefficient for z. \n \b Output: \a partial [ \a i_x * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of H( x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Output: \a partial [ \a i_z * \a nc_partial + k ] for k = 0 , ... , \a d may be used as work space; i.e., may change in an unspecified manner. \par Checked Assumptions \li NumArg(op) == 1 \li NumRes(op) == 1 \li \a i_x < \a i_z \li \a d < \a cap_order \li \a d < \a nc_partial */ template inline void reverse_unary1_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } // ==================== Unary operators with two results ==================== /*! Prototype for forward mode unary operator with two results (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param p lowest order of the Taylor coefficients that we are computing. \param q highest order of the Taylor coefficients that we are computing. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. The auxillary result is called y has index \a i_z - 1. \param i_x variable index corresponding to the argument for this operator; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: taylor [ i_x * cap_order + k ] for k = 0 , ... , q, is the k-th order Taylor coefficient corresponding to x. \n \b Input: taylor [ i_z * cap_order + k ] for k = 0 , ... , p - 1, is the k-th order Taylor coefficient corresponding to z. \n \b Input: taylor [ ( i_z - 1) * cap_order + k ] for k = 0 , ... , p-1, is the k-th order Taylor coefficient corresponding to the auxillary result y. \n \b Output: taylor [ i_z * cap_order + k ], for k = p , ... , q, is the k-th order Taylor coefficient corresponding to z. \n \b Output: taylor [ ( i_z - 1 ) * cap_order + k ], for k = p , ... , q, is the k-th order Taylor coefficient corresponding to the autillary result y. \par Checked Assertions \li NumArg(op) == 1 \li NumRes(op) == 2 \li i_x + 1 < i_z \li q < cap_order \li p <= q */ template inline void forward_unary2_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for multiple direction forward mode unary operator with two results (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param q order of the Taylor coefficients that we are computing. \param r number of directions for Taylor coefficients that we are computing. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. The auxillary result is called y has index \a i_z - 1. \param i_x variable index corresponding to the argument for this operator; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the \c taylor array. \par tpv We use the notation tpv = (cap_order-1) * r + 1 which is the number of Taylor coefficients per variable \param taylor \b Input: taylor [ i_x * tpv + 0 ] is the zero order Taylor coefficient for all directions and taylor [ i_x * tpv + (k-1)*r + ell + 1 for k = 1 , ... , q, ell = 0 , ..., r-1, is the k-th order Taylor coefficient corresponding to x and the ell-th direction. \n \b Input: taylor [ i_z * tpv + 0 ], is the zero order Taylor coefficient for all directions and taylor [ i_z * tpv + (k-1)*r + ell + 1 ], for k = 1 , ... , q-1, ell = 0, ..., r-1, is the k-th order Taylor coefficient corresponding to z and the ell-th direction. \n \b Input: taylor [ (i_z-1) * tpv + 0 ], is the zero order Taylor coefficient for all directions and taylor [ (i_z-1) * tpv + (k-1)*r + ell + 1 ], for k = 1 , ... , q-1, ell = 0, ..., r-1, is the k-th order Taylor coefficient corresponding to the auxillary result y and the ell-th direction. \n \b Output: taylor [ i_z * tpv + (q-1)*r + ell + 1], ell = 0, ..., r-1, is the q-th order Taylor coefficient corresponding to z and the ell-th direction. \par Checked Assertions \li NumArg(op) == 1 \li NumRes(op) == 2 \li i_x + 1 < i_z \li 0 < q \li q < cap_order */ template inline void forward_unary2_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for zero order forward mode unary operator with two results (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. The auxillary result is called y and has index \a i_z - 1. \param i_x variable index corresponding to the argument for this operator; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: \a taylor [ \a i_x * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to x. \n \b Output: \a taylor [ \a i_z * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to z. \n \b Output: \a taylor [ ( \a i_z - 1 ) * \a cap_order + j ] is the j-th order Taylor coefficient corresponding to the autillary result y. \par Checked Assertions \li NumArg(op) == 1 \li NumRes(op) == 2 \li \a i_x + 1 < \a i_z \li \a j < \a cap_order */ template inline void forward_unary2_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for reverse mode unary operator with two results (not used). This routine is given the partial derivatives of a function G( z , y , x , w , ... ) and it uses them to compute the partial derivatives of \verbatim H( x , w , u , ... ) = G[ z(x) , y(x), x , w , u , ... ] \endverbatim \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param d highest order Taylor coefficient that we are computing the partial derivatives with respect to. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor to z. The auxillary result is called y and has index \a i_z - 1. \param i_x variable index corresponding to the argument for this operation; i.e. the row index in \a taylor corresponding to x. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \a taylor [ \a i_x * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to x. \n \a taylor [ \a i_z * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to z. \n \a taylor [ ( \a i_z - 1) * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to the auxillary variable y. \param nc_partial number of colums in the matrix containing all the partial derivatives. \param partial \b Input: \a partial [ \a i_x * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Input: \a partial [ \a i_z * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for z. \n \b Input: \a partial [ ( \a i_z - 1) * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , x , w , u , ... ) with respect to the k-th order Taylor coefficient for the auxillary variable y. \n \b Output: \a partial [ \a i_x * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of H( x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Output: \a partial [ \a ( i_z - j ) * \a nc_partial + k ] for j = 0 , 1 , and for k = 0 , ... , \a d may be used as work space; i.e., may change in an unspecified manner. \par Checked Assumptions \li NumArg(op) == 1 \li NumRes(op) == 2 \li \a i_x + 1 < \a i_z \li \a d < \a cap_order \li \a d < \a nc_partial */ template inline void reverse_unary2_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } // =================== Binary operators with one result ==================== /*! Prototype forward mode x op y (not used) \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param p lowest order of the Taylor coefficient that we are computing. \param q highest order of the Taylor coefficient that we are computing. \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param arg \a arg[0] index corresponding to the left operand for this operator; i.e. the index corresponding to x. \n \a arg[1] index corresponding to the right operand for this operator; i.e. the index corresponding to y. \param parameter If x is a parameter, \a parameter [ \a arg[0] ] is the value corresponding to x. \n If y is a parameter, \a parameter [ \a arg[1] ] is the value corresponding to y. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: If x is a variable, taylor [ arg[0] * cap_order + k ], for k = 0 , ... , q, is the k-th order Taylor coefficient corresponding to x. \n \b Input: If y is a variable, taylor [ arg[1] * cap_order + k ], for k = 0 , ... , q, is the k-th order Taylor coefficient corresponding to y. \n \b Input: taylor [ i_z * cap_order + k ], for k = 0 , ... , p-1, is the k-th order Taylor coefficient corresponding to z. \n \b Output: taylor [ i_z * cap_order + k ], for k = p, ... , q, is the k-th order Taylor coefficient corresponding to z. \par Checked Assertions \li NumArg(op) == 2 \li NumRes(op) == 1 \li q < cap_order \li p <= q */ template inline void forward_binary_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype multiple direction forward mode x op y (not used) \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param q is the order of the Taylor coefficients that we are computing. \param r number of directions for Taylor coefficients that we are computing \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param arg \a arg[0] index corresponding to the left operand for this operator; i.e. the index corresponding to x. \n \a arg[1] index corresponding to the right operand for this operator; i.e. the index corresponding to y. \param parameter If x is a parameter, \a parameter [ \a arg[0] ] is the value corresponding to x. \n If y is a parameter, \a parameter [ \a arg[1] ] is the value corresponding to y. \param cap_order maximum number of orders that will fit in the \c taylor array. \par tpv We use the notation tpv = (cap_order-1) * r + 1 which is the number of Taylor coefficients per variable \param taylor \b Input: If x is a variable, taylor [ arg[0] * tpv + 0 ], is the zero order Taylor coefficient for all directions and taylor [ arg[0] * tpv + (k-1)*r + ell + 1 ], for k = 1 , ... , q, ell = 0, ..., r-1, is the k-th order Taylor coefficient corresponding to x and the ell-th direction. \n \b Input: If y is a variable, taylor [ arg[1] * tpv + 0 ], is the zero order Taylor coefficient for all directions and taylor [ arg[1] * tpv + (k-1)*r + ell + 1 ], for k = 1 , ... , q, ell = 0, ..., r-1, is the k-th order Taylor coefficient corresponding to y and the ell-th direction. \n \b Input: taylor [ i_z * tpv + 0 ], is the zero order Taylor coefficient for all directions and taylor [ i_z * tpv + (k-1)*r + ell + 1 ], for k = 1 , ... , q-1, ell = 0, ..., r-1, is the k-th order Taylor coefficient corresponding to z and the ell-th direction. \n \b Output: taylor [ i_z * tpv + (q-1)*r + ell + 1], ell = 0, ..., r-1, is the q-th order Taylor coefficient corresponding to z and the ell-th direction. \par Checked Assertions \li NumArg(op) == 2 \li NumRes(op) == 1 \li 0 < q < cap_order */ template inline void forward_binary_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype zero order forward mode x op y (not used) \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param arg \a arg[0] index corresponding to the left operand for this operator; i.e. the index corresponding to x. \n \a arg[1] index corresponding to the right operand for this operator; i.e. the index corresponding to y. \param parameter If x is a parameter, \a parameter [ \a arg[0] ] is the value corresponding to x. \n If y is a parameter, \a parameter [ \a arg[1] ] is the value corresponding to y. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: If x is a variable, \a taylor [ \a arg[0] * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to x. \n \b Input: If y is a variable, \a taylor [ \a arg[1] * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to y. \n \b Output: \a taylor [ \a i_z * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to z. \par Checked Assertions \li NumArg(op) == 2 \li NumRes(op) == 1 */ template inline void forward_binary_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for reverse mode binary operator x op y (not used). This routine is given the partial derivatives of a function G( z , y , x , w , ... ) and it uses them to compute the partial derivatives of \verbatim H( y , x , w , u , ... ) = G[ z(x , y) , y , x , w , u , ... ] \endverbatim \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param d highest order Taylor coefficient that we are computing the partial derivatives with respect to. \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param arg \a arg[0] index corresponding to the left operand for this operator; i.e. the index corresponding to x. \n \a arg[1] index corresponding to the right operand for this operator; i.e. the index corresponding to y. \param parameter If x is a parameter, \a parameter [ \a arg[0] ] is the value corresponding to x. \n If y is a parameter, \a parameter [ \a arg[1] ] is the value corresponding to y. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \a taylor [ \a i_z * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to z. \n If x is a variable, \a taylor [ \a arg[0] * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to x. \n If y is a variable, \a taylor [ \a arg[1] * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to y. \param nc_partial number of colums in the matrix containing all the partial derivatives. \param partial \b Input: \a partial [ \a i_z * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for z. \n \b Input: If x is a variable, \a partial [ \a arg[0] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Input: If y is a variable, \a partial [ \a arg[1] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , x , w , u , ... ) with respect to the k-th order Taylor coefficient for the auxillary variable y. \n \b Output: If x is a variable, \a partial [ \a arg[0] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of H( y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Output: If y is a variable, \a partial [ \a arg[1] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of H( y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for y. \n \b Output: \a partial [ \a i_z * \a nc_partial + k ] for k = 0 , ... , \a d may be used as work space; i.e., may change in an unspecified manner. \par Checked Assumptions \li NumArg(op) == 2 \li NumRes(op) == 1 \li \a If x is a variable, arg[0] < \a i_z \li \a If y is a variable, arg[1] < \a i_z \li \a d < \a cap_order \li \a d < \a nc_partial */ template inline void reverse_binary_op( size_t d , size_t i_z , addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } // ======================= Pow Function =================================== /*! Prototype for forward mode z = pow(x, y) (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param p lowest order of the Taylor coefficient that we are computing. \param q highest order of the Taylor coefficient that we are computing. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. Note that there are three results for this operation, below they are referred to as z_0, z_1, z_2 and correspond to \verbatim z_0 = log(x) z_1 = z0 * y z_2 = exp(z1) \endverbatim It follows that the final result is equal to z; i.e., z = z_2 = pow(x, y). \param arg \a arg[0] index corresponding to the left operand for this operator; i.e. the index corresponding to x. \n \a arg[1] index corresponding to the right operand for this operator; i.e. the index corresponding to y. \param parameter If x is a parameter, \a parameter [ \a arg[0] ] is the value corresponding to x. \n If y is a parameter, \a parameter [ \a arg[1] ] is the value corresponding to y. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: If x is a variable, taylor [ arg[0] * cap_order + k ] for k = 0 , ... , q, is the k-th order Taylor coefficient corresponding to x. \n \b Input: If y is a variable, taylor [ arg[1] * cap_order + k ] for k = 0 , ... , q is the k-th order Taylor coefficient corresponding to y. \n \b Input: taylor [ (i_z-2+j) * cap_order + k ], for j = 0, 1, 2 , for k = 0 , ... , p-1, is the k-th order Taylor coefficient corresponding to z_j. \n \b Output: taylor [ (i_z-2+j) * cap_order + k ], is the k-th order Taylor coefficient corresponding to z_j. \par Checked Assertions \li NumArg(op) == 2 \li NumRes(op) == 3 \li If x is a variable, arg[0] < i_z - 2 \li If y is a variable, arg[1] < i_z - 2 \li q < cap_order \li p <= q */ template inline void forward_pow_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for multiple direction forward mode z = pow(x, y) (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param q order of the Taylor coefficient that we are computing. \param r is the number of Taylor coefficient directions that we are computing \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. Note that there are three results for this operation, below they are referred to as z_0, z_1, z_2 and correspond to \verbatim z_0 = log(x) z_1 = z0 * y z_2 = exp(z1) \endverbatim It follows that the final result is equal to z; i.e., z = z_2 = pow(x, y). \param arg \a arg[0] index corresponding to the left operand for this operator; i.e. the index corresponding to x. \n \a arg[1] index corresponding to the right operand for this operator; i.e. the index corresponding to y. \param parameter If x is a parameter, \a parameter [ \a arg[0] ] is the value corresponding to x. \n If y is a parameter, \a parameter [ \a arg[1] ] is the value corresponding to y. \param cap_order maximum number of orders that will fit in the \c taylor array. \par tpv We use the notation tpv = (cap_order-1) * r + 1 which is the number of Taylor coefficients per variable \param taylor \b Input: If x is a variable, taylor [ arg[0] * tpv + 0 ] is the zero order coefficient corresponding to x and taylor [ arg[0] * tpv + (k-1)*r+1+ell ] for k = 1 , ... , q, ell = 0 , ... , r-1, is the k-th order Taylor coefficient corresponding to x for the ell-th direction. \n \n \b Input: If y is a variable, taylor [ arg[1] * tpv + 0 ] is the zero order coefficient corresponding to y and taylor [ arg[1] * tpv + (k-1)*r+1+ell ] for k = 1 , ... , q, ell = 0 , ... , r-1, is the k-th order Taylor coefficient corresponding to y for the ell-th direction. \n \n \b Input: taylor [ (i_z-2+j) * tpv + 0 ], is the zero order coefficient corresponding to z_j and taylor [ (i_z-2+j) * tpv + (k-1)*r+1+ell ], for j = 0, 1, 2 , k = 0 , ... , q-1, ell = 0, ... , r-1, is the k-th order Taylor coefficient corresponding to z_j for the ell-th direction. \n \n \b Output: taylor [ (i_z-2+j) * tpv + (q-1)*r+1+ell ], for j = 0, 1, 2 , ell = 0, ... , r-1, is the q-th order Taylor coefficient corresponding to z_j for the ell-th direction. \par Checked Assertions \li NumArg(op) == 2 \li NumRes(op) == 3 \li If x is a variable, arg[0] < i_z - 2 \li If y is a variable, arg[1] < i_z - 2 \li 0 < q \li q < cap_order */ template inline void forward_pow_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for zero order forward mode z = pow(x, y) (not used). \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. Note that there are three results for this operation, below they are referred to as z_0, z_1, z_2 and correspond to \verbatim z_0 = log(x) z_1 = z0 * y z_2 = exp(z1) \endverbatim It follows that the final result is equal to z; i.e., z = z_2 = pow(x, y). \param arg \a arg[0] index corresponding to the left operand for this operator; i.e. the index corresponding to x. \n \a arg[1] index corresponding to the right operand for this operator; i.e. the index corresponding to y. \param parameter If x is a parameter, \a parameter [ \a arg[0] ] is the value corresponding to x. \n If y is a parameter, \a parameter [ \a arg[1] ] is the value corresponding to y. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \b Input: If x is a variable, \a taylor [ \a arg[0] * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to x. \n \b Input: If y is a variable, \a taylor [ \a arg[1] * \a cap_order + 0 ] is the k-th order Taylor coefficient corresponding to y. \n \b Output: \a taylor [ \a (i_z - 2 + j) * \a cap_order + 0 ] is the zero order Taylor coefficient corresponding to z_j. \par Checked Assertions \li NumArg(op) == 2 \li NumRes(op) == 3 \li If x is a variable, \a arg[0] < \a i_z - 2 \li If y is a variable, \a arg[1] < \a i_z - 2 */ template inline void forward_pow_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for reverse mode z = pow(x, y) (not used). This routine is given the partial derivatives of a function G( z , y , x , w , ... ) and it uses them to compute the partial derivatives of \verbatim H( y , x , w , u , ... ) = G[ pow(x , y) , y , x , w , u , ... ] \endverbatim \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base . \param d highest order Taylor coefficient that we are computing the partial derivatives with respect to. \param i_z variable index corresponding to the last (primary) result for this operation; i.e. the row index in \a taylor corresponding to z. Note that there are three results for this operation, below they are referred to as z_0, z_1, z_2 and correspond to \verbatim z_0 = log(x) z_1 = z0 * y z_2 = exp(z1) \endverbatim It follows that the final result is equal to z; i.e., z = z_2 = pow(x, y). \param arg \a arg[0] index corresponding to the left operand for this operator; i.e. the index corresponding to x. \n \a arg[1] index corresponding to the right operand for this operator; i.e. the index corresponding to y. \param parameter If x is a parameter, \a parameter [ \a arg[0] ] is the value corresponding to x. \n If y is a parameter, \a parameter [ \a arg[1] ] is the value corresponding to y. \param cap_order maximum number of orders that will fit in the \c taylor array. \param taylor \a taylor [ \a (i_z - 2 + j) * \a cap_order + k ] for j = 0, 1, 2 and k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to z_j. \n If x is a variable, \a taylor [ \a arg[0] * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to x. \n If y is a variable, \a taylor [ \a arg[1] * \a cap_order + k ] for k = 0 , ... , \a d is the k-th order Taylor coefficient corresponding to y. \param nc_partial number of colums in the matrix containing all the partial derivatives. \param partial \b Input: \a partial [ \a (i_z - 2 + j) * \a nc_partial + k ] for j = 0, 1, 2, and k = 0 , ... , \a d is the partial derivative of G( z , y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for z_j. \n \b Input: If x is a variable, \a partial [ \a arg[0] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Input: If y is a variable, \a partial [ \a arg[1] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of G( z , x , w , u , ... ) with respect to the k-th order Taylor coefficient for the auxillary variable y. \n \b Output: If x is a variable, \a partial [ \a arg[0] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of H( y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for x. \n \b Output: If y is a variable, \a partial [ \a arg[1] * \a nc_partial + k ] for k = 0 , ... , \a d is the partial derivative of H( y , x , w , u , ... ) with respect to the k-th order Taylor coefficient for y. \n \b Output: \a partial [ \a ( i_z - j ) * \a nc_partial + k ] for j = 0 , 1 , 2 and for k = 0 , ... , \a d may be used as work space; i.e., may change in an unspecified manner. \par Checked Assumptions \li NumArg(op) == 2 \li NumRes(op) == 3 \li \a If x is a variable, arg[0] < \a i_z - 2 \li \a If y is a variable, arg[1] < \a i_z - 2 \li \a d < \a cap_order \li \a d < \a nc_partial */ template inline void reverse_pow_op( size_t d , size_t i_z , addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } // ==================== Sparsity Calculations ============================== /*! Prototype for reverse mode Hessian sparsity unary operators. This routine is given the forward mode Jacobian sparsity patterns for x. It is also given the reverse mode dependence of G on z. In addition, it is given the revese mode Hessian sparsity for the quanity of interest G(z , y , ... ) and it uses them to compute the sparsity patterns for \verbatim H( x , w , u , ... ) = G[ z(x) , x , w , u , ... ] \endverbatim \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e. the row index in sparsity corresponding to z. \param i_x variable index corresponding to the argument for this operator; i.e. the row index in sparsity corresponding to x. \param rev_jacobian \a rev_jacobian[i_z] is all false (true) if the Jacobian of G with respect to z must be zero (may be non-zero). \n \n \a rev_jacobian[i_x] is all false (true) if the Jacobian with respect to x must be zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. \param for_jac_sparsity The set with index \a i_x in for_jac_sparsity is the forward mode Jacobian sparsity pattern for the variable x. \param rev_hes_sparsity The set with index \a i_z in in \a rev_hes_sparsity is the Hessian sparsity pattern for the fucntion G where one of the partials derivative is with respect to z. \n \n The set with index \a i_x in \a rev_hes_sparsity is the Hessian sparsity pattern where one of the partials derivative is with respect to x. On input, it corresponds to the function G, and on output it corresponds to the function H. \par Checked Assertions: \li \a i_x < \a i_z */ template inline void reverse_sparse_hessian_unary_op( size_t i_z , size_t i_x , bool* rev_jacobian , Vector_set& for_jac_sparsity , Vector_set& rev_hes_sparsity ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Prototype for reverse mode Hessian sparsity binary operators. This routine is given the sparsity patterns the Hessian of a function G(z, y, x, ... ) and it uses them to compute the sparsity patterns for the Hessian of \verbatim H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ] \endverbatim \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e. the row index in sparsity corresponding to z. \param arg \a arg[0] variable index corresponding to the left operand for this operator; i.e. the set with index \a arg[0] in \a var_sparsity is the spasity pattern correspoding to x. \n \n arg[1] variable index corresponding to the right operand for this operator; i.e. the row index in sparsity patterns corresponding to y. \param jac_reverse \a jac_reverse[i_z] is false (true) if the Jacobian of G with respect to z is always zero (may be non-zero). \n \n \a jac_reverse[ \a arg[0] ] is false (true) if the Jacobian with respect to x is always zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. \n \n \a jac_reverse[ \a arg[1] ] is false (true) if the Jacobian with respect to y is always zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. \param for_jac_sparsity The set with index \a arg[0] in \a for_jac_sparsity for the is the forward Jacobian sparsity pattern for x. \n \n The set with index \a arg[1] in \a for_jac_sparsity is the forward sparsity pattern for y. \param rev_hes_sparsity The set wiht index \a i_x in \a rev_hes_sparsity is the Hessian sparsity pattern for the function G where one of the partial derivatives is with respect to z. \n \n The set with index \a arg[0] in \a rev_hes_sparsity is the Hessian sparsity pattern where one of the partial derivatives is with respect to x. On input, it corresponds to the function G, and on output it correspondst to H. \n \n The set with index \a arg[1] in \a rev_hes_sparsity is the Hessian sparsity pattern where one of the partial derivatives is with respect to y. On input, it corresponds to the function G, and on output it correspondst to H. \par Checked Assertions: \li \a arg[0] < \a i_z \li \a arg[1] < \a i_z */ template inline void reverse_sparse_hessian_binary_op( size_t i_z , const addr_t* arg , bool* jac_reverse , Vector_set& for_jac_sparsity , Vector_set& rev_hes_sparsity ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/for_one.hpp0000644000176200001440000001025514536067013017625 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FOR_ONE_INCLUDED # define CPPAD_FOR_ONE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ForOne$$ $spell dy typename Taylor const $$ $index partial, first order driver$$ $index first, order partial driver$$ $index driver, first order partial$$ $index easy, partial$$ $index driver, easy partial$$ $index partial, easy$$ $section First Order Partial Derivative: Driver Routine$$ $head Syntax$$ $icode%dy% = %f%.ForOne(%x%, %j%)%$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. The syntax above sets $icode dy$$ to the partial of $latex F$$ with respect to $latex x_j$$; i.e., $latex \[ dy = \D{F}{ x_j } (x) = \left[ \D{ F_0 }{ x_j } (x) , \cdots , \D{ F_{m-1} }{ x_j } (x) \right] \] $$ $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/ForOne Uses Forward/ForOne/ForOne Uses Forward/$$ below). $head x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ (see $cref/Vector/ForOne/Vector/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies that point at which to evaluate the partial derivative. $head j$$ The argument $icode j$$ has prototype $codei% size_t %j% %$$ an is less than $icode n$$, $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies the component of $icode F$$ for which we are computing the partial derivative. $head dy$$ The result $icode dy$$ has prototype $codei% %Vector% %dy% %$$ (see $cref/Vector/ForOne/Vector/$$ below) and its size is $latex m$$, the dimension of the $cref/range/seq_property/Range/$$ space for $icode f$$. The value of $icode dy$$ is the partial of $latex F$$ with respect to $latex x_j$$ evaluated at $icode x$$; i.e., for $latex i = 0 , \ldots , m - 1$$ $latex \[. dy[i] = \D{ F_i }{ x_j } ( x ) \] $$ $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Base$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head ForOne Uses Forward$$ After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After a call to $code ForOne$$, the zero order Taylor coefficients correspond to $icode%f%.Forward(0,%x%)%$$ and the other coefficients are unspecified. $head Example$$ $children% example/for_one.cpp %$$ The routine $cref/ForOne/for_one.cpp/$$ is both an example and test. It returns $code true$$, if it succeeds and $code false$$ otherwise. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template template Vector ADFun::ForOne(const Vector &x, size_t j) { size_t j1; size_t n = Domain(); size_t m = Range(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( x.size() == n, "ForOne: Length of x not equal domain dimension for f" ); CPPAD_ASSERT_KNOWN( j < n, "ForOne: the index j is not less than domain dimension for f" ); // point at which we are evaluating the second partials Forward(0, x); // direction in which are are taking the derivative Vector dx(n); for(j1 = 0; j1 < n; j1++) dx[j1] = Base(0); dx[j] = Base(1); // dimension the return value Vector dy(m); // compute the return value dy = Forward(1, dx); return dy; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/ad_valued.hpp0000644000176200001440000000271014536067013020117 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_AD_VALUED_INCLUDED # define CPPAD_AD_VALUED_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ADValued$$ $spell $$ $index operation, AD valued$$ $index function, AD valued$$ $section AD Valued Operations and Functions$$ $comment atomic.omh includes atomic_base.omh which atomic_base.hpp$$ $childtable% cppad/local/arithmetic.hpp% cppad/local/std_math_ad.hpp% cppad/local/math_other.hpp% cppad/local/cond_exp.hpp% cppad/local/discrete.hpp% omh/atomic.omh %$$ $end */ // include MathOther.h after CondExp.h because some MathOther.h routines use // CondExp.h and CondExp.h is not sufficently declared in Declare.h # include # include # include # include # include # include # include # include # endif TMB/inst/include/cppad/local/hash_code.hpp0000644000176200001440000001464214536067013020117 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_HASH_CODE_INCLUDED # define CPPAD_HASH_CODE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file hash_code.hpp CppAD hashing utility. */ /*! \def CPPAD_HASH_TABLE_SIZE the codes retruned by hash_code are between zero and CPPAD_HASH_TABLE_SIZE minus one. */ # define CPPAD_HASH_TABLE_SIZE 10000 /*! General purpose hash code for an arbitrary value. \tparam Value is the type of the argument being hash coded. It should be a plain old data class; i.e., the values included in the equality operator in the object and not pointed to by the object. \param value the value that we are generating a hash code for. \return is a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1. \par Checked Assertions \li \c std::numeric_limits::max() >= CPPAD_HASH_TABLE_SIZE \li \c sizeof(value) is even \li \c sizeof(unsigned short) == 2 */ template unsigned short hash_code(const Value& value) { CPPAD_ASSERT_UNKNOWN( std::numeric_limits::max() >= CPPAD_HASH_TABLE_SIZE ); CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 ); CPPAD_ASSERT_UNKNOWN( sizeof(value) % 2 == 0 ); # const unsigned short* v = reinterpret_cast(& value); # size_t i = sizeof(value) / 2 - 1; # unsigned short code = v[i]; # while(i--) code += v[i]; return code % CPPAD_HASH_TABLE_SIZE; } /*! Specialized hash code for a CppAD operator and its arguments. \param op is the operator that we are computing a hash code for. If it is not one of the following operartors, the operator is not hash coded and zero is returned: \li unary operators: AbsOp, AcosOp, AsinOp, AtanOp, CosOp, CoshOp ExpOp, LogOp, SinOp, SinhOp, SqrtOp, TanOp, TanhOp \li binary operators where first argument is a parameter: AddpvOp, DivpvOp, MulpvOp, PowpvOp, SubpvOp, \li binary operators where second argument is a parameter: DivvpOp, PowvpOp, SubvpOp \li binary operators where first is an index and second is a variable: DisOp \li binary operators where both arguments are variables: AddvvOp, DivvvOp, MulvvOp, PowvvOp, SubvvOp \param arg is a vector of length \c NumArg(op) or 2 (which ever is smaller), containing the corresponding argument indices for this operator. \param npar is the number of parameters corresponding to this operation sequence. \param par is a vector of length \a npar containing the parameters for this operation sequence; i.e., given a parameter index of \c i, the corresponding parameter value is \a par[i]. \return is a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1. \par Checked Assertions \c op must be one of the operators specified above. In addition, \li \c std::numeric_limits::max() >= CPPAD_HASH_TABLE_SIZE \li \c sizeof(size_t) is even \li \c sizeof(Base) is even \li \c sizeof(unsigned short) == 2 \li \c size_t(op) < size_t(NumberOp) <= CPPAD_HASH_TABLE_SIZE \li if the j-th argument for this operation is a parameter, arg[j] < npar. */ template unsigned short hash_code( OpCode op , const addr_t* arg , size_t npar , const Base* par ) { CPPAD_ASSERT_UNKNOWN( std::numeric_limits::max() >= CPPAD_HASH_TABLE_SIZE ); CPPAD_ASSERT_UNKNOWN( size_t (op) < size_t(NumberOp) ); CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 ); CPPAD_ASSERT_UNKNOWN( sizeof(addr_t) % 2 == 0 ); CPPAD_ASSERT_UNKNOWN( sizeof(Base) % 2 == 0 ); unsigned short op_fac = static_cast ( CPPAD_HASH_TABLE_SIZE / static_cast(NumberOp) ); CPPAD_ASSERT_UNKNOWN( op_fac > 0 ); // number of shorts per addr_t value size_t short_addr_t = sizeof(addr_t) / 2; // number of shorts per Base value size_t short_base = sizeof(Base) / 2; // initialize with value that separates operators as much as possible unsigned short code = static_cast( static_cast(op) * op_fac ); // now code in the operands size_t i; const unsigned short* v; // first argument switch(op) { // Binary operators where first arugment is a parameter. // Code parameters by value instead of // by index for two reasons. One, it gives better separation. // Two, different indices can be same parameter value. case AddpvOp: case DivpvOp: case MulpvOp: case PowpvOp: case SubpvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); v = reinterpret_cast(par + arg[0]); i = short_base; while(i--) code += v[i]; v = reinterpret_cast(arg + 1); i = short_addr_t; while(i--) code += v[i]; break; // Binary operator where first argument is an index and // second is a variable (same as both variables). case DisOp: // Binary operators where both arguments are variables case AddvvOp: case DivvvOp: case MulvvOp: case PowvvOp: case SubvvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); v = reinterpret_cast(arg + 0); i = 2 * short_addr_t; while(i--) code += v[i]; break; // Binary operators where second arugment is a parameter. case DivvpOp: case PowvpOp: case SubvpOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); v = reinterpret_cast(arg + 0); i = short_addr_t; while(i--) code += v[i]; v = reinterpret_cast(par + arg[1]); i = short_base; while(i--) code += v[i]; break; // Unary operators case AbsOp: case AcosOp: case AsinOp: case AtanOp: case CosOp: case CoshOp: case ErfOp: case ExpOp: case LogOp: case SignOp: case SinOp: case SinhOp: case SqrtOp: case TanOp: case TanhOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 || op == ErfOp ); v = reinterpret_cast(arg + 0); i = short_addr_t; while(i--) code += v[i]; break; // should have been one of he cases above default: CPPAD_ASSERT_UNKNOWN(false); } return code % CPPAD_HASH_TABLE_SIZE; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sparse_list.hpp0000644000176200001440000003700714536067013020532 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_LIST_INCLUDED # define CPPAD_SPARSE_LIST_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sparse_list.hpp Vector of sets of positive integers stored as singly linked lists. */ /*! Vector of sets of positive integers, each set stored as a singly linked list. */ class sparse_list { public: /// type used for each set in the vector of sets /// (note that next is index in data_ for next element in this set). struct pair_size_t { size_t value; size_t next; }; private: // ----------------------------------------------------------------- /// Number of sets that we are representing /// (set by constructor and resize). size_t n_set_; /// Possible elements in each set are 0, 1, ..., end_ - 1; size_t end_; /// The data for all the elements in all the sets CppAD::pod_vector data_; /// next element pair_size_t next_pair_; /// number of elements in data_ that are no longer being used. size_t data_not_used_; /// temporary data vector used for garbage collection CppAD::pod_vector data_tmp_; // ----------------------------------------------------------------- /*! Private member function that counts number of elements in a set. \param index is the index of the set we are counting. \par Checked Assertions \li index < n_set_ */ size_t number_elements(size_t index) const { CPPAD_ASSERT_UNKNOWN(index < n_set_ ); size_t count = 0; size_t i = index; size_t value = data_[i].value; while( value < end_ ) { count++; i = data_[i].next; value = data_[i].value; } return count; } // ----------------------------------------------------------------- /// Private member functions that does garbage collection. void collect_garbage(void) { CPPAD_ASSERT_UNKNOWN( 2 * data_not_used_ > data_.size() ); // CPPAD_ASSERT_UNKNOWN( number_elements() + n_set_ + data_not_used_ == data_.size() ); // copy the sets to a temporary data vector data_tmp_.erase(); data_tmp_.extend(n_set_); for(size_t i = 0; i < n_set_; i++) { size_t next = i; size_t next_tmp = i; // size_t value = data_[next].value; while( value < end_ ) { data_tmp_[next_tmp].value = value; // data_tmp_[next_tmp].next = data_tmp_.extend(1); // does not seem to work ? size_t index_tmp = data_tmp_.extend(1); data_tmp_[next_tmp].next = index_tmp; // next = data_[next].next; next_tmp = data_tmp_[next_tmp].next; // value = data_[next].value; } data_tmp_[next_tmp].value = end_; } CPPAD_ASSERT_UNKNOWN( data_tmp_.size() + data_not_used_ == data_.size() ); // swap the tmp and old data vectors data_.swap(data_tmp_); // all of the elements are used in this new version of data_ data_not_used_ = 0; } public: // ----------------------------------------------------------------- /*! Default constructor (no sets) */ sparse_list(void) : n_set_(0) , end_(0) , data_not_used_(0) { next_pair_.value = end_; } // ----------------------------------------------------------------- /*! Using copy constructor is a programing (not user) error \param v vector that we are attempting to make a copy of. */ sparse_list(const sparse_list& v) { // Error: // Probably a sparse_list argument has been passed by value CPPAD_ASSERT_UNKNOWN(false); } // ----------------------------------------------------------------- /*! Destructor */ ~sparse_list(void) { } // ----------------------------------------------------------------- /*! Change number of sets, end marker, and initialize all sets as empty If \c n_set_in is zero, any memory currently allocated for this object is freed. Otherwise, new memory may be allocated for the sets (if needed). \param n_set_in is the number of sets in this vector of sets. \param end_in is the maximum element plus one (the minimum element is 0). */ void resize(size_t n_set_in, size_t end_in) { n_set_ = n_set_in; end_ = end_in; next_pair_.value = end_in; data_not_used_ = 0; if( n_set_in == 0 ) { // free all memory connected with this object data_.free(); return; } // now start a new vector with empty sets data_.erase(); data_.extend(n_set_); for(size_t i = 0; i < n_set_; i++) data_[i].value = end_; } // ----------------------------------------------------------------- /*! Add one element to a set. \param index is the index for this set in the vector of sets. \param element is the element we are adding to the set. \par Checked Assertions \li index < n_set_ \li element < end_ */ void add_element(size_t index, size_t element) { CPPAD_ASSERT_UNKNOWN( index < n_set_ ); CPPAD_ASSERT_UNKNOWN( element < end_ ); size_t value = data_[index].value; // case of inserting at beginning if( element < value ) { size_t insert = data_.extend(1); data_[insert] = data_[index]; data_[index].value = element; data_[index].next = insert; return; } // search list for place to insert size_t previous = index; size_t current = data_[previous].next; value = data_[current].value; while( value < element ) { previous = current; current = data_[previous].next; value = data_[current].value; } if( element != value ) { CPPAD_ASSERT_UNKNOWN( element < value ); size_t insert = data_.extend(1); // data_[insert].next = data_[previous].next; data_[previous].next = insert; data_[insert].value = element; } } // ----------------------------------------------------------------- /*! Is an element in a set. \param index is the index for this set in the vector of sets. \param element is the element we are checking to see if it is in set. \par Checked Assertions \li index < n_set_ \li element < end_ */ bool is_element(size_t index, size_t element) { CPPAD_ASSERT_UNKNOWN( index < n_set_ ); CPPAD_ASSERT_UNKNOWN( element < end_ ); size_t i = index; size_t value = data_[i].value; while( value < element ) { i = data_[i].next; value = data_[i].value; } return element == value; } // ----------------------------------------------------------------- /*! Begin retrieving elements from one of the sets. \param index is the index for the set that is going to be retrieved. The elements of the set are retrieved in increasing order. \par Checked Assertions \li index < n_set_ */ void begin(size_t index) { // initialize element to search for in this set CPPAD_ASSERT_UNKNOWN( index < n_set_ ); next_pair_ = data_[index]; return; } // ----------------------------------------------------------------- /*! Get the next element from the current retrieval set. \return is the next element in the set with index specified by the previous call to \c begin. If no such element exists, \c this->end() is returned. \par Assumption There is no call to \c add_element or \c binary_union since the previvious \c begin */ size_t next_element(void) { size_t element = next_pair_.value; if( element != end_ ) next_pair_ = data_[next_pair_.next]; return element; } // ----------------------------------------------------------------- /*! Assign the empty set to one of the sets. \param target is the index of the set we are setting to the empty set. \par data_not_used_ increments this value by number of elements lost. \par Checked Assertions \li target < n_set_ */ void clear(size_t target) { CPPAD_ASSERT_UNKNOWN( target < n_set_ ); // number of elements that will be deleted by this operation size_t number_delete = number_elements(target); // delete the elements from the set data_[target].value = end_; // adjust data_not_used_ data_not_used_ += number_delete; if( 2 * data_not_used_ > data_.size() ) collect_garbage(); } // ----------------------------------------------------------------- /*! Assign one set equal to another set. \param this_target is the index (in this \c sparse_list object) of the set being assinged. \param other_source is the index (in the other \c sparse_list object) of the that we are using as the value to assign to the target set. \param other is the other \c sparse_list object (which may be the same as this \c sparse_list object). \par data_not_used_ increments this value by number of elements lost. \par Checked Assertions \li this_target < n_set_ \li other_index < other.n_set_ */ void assignment( size_t this_target , size_t other_source , const sparse_list& other ) { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ ); CPPAD_ASSERT_UNKNOWN( other_source < other.n_set_ ); CPPAD_ASSERT_UNKNOWN( end_ == other.end() ); // check if we are assigning a set to itself if( (this == &other) & (this_target == other_source) ) return; // number of elements that will be deleted by this operation size_t number_delete = number_elements(this_target); size_t this_index = this_target; size_t other_index = other_source; size_t value = other.data_[other_index].value; while( value != end_ ) { size_t next = data_.extend(1); data_[this_index].value = value; data_[this_index].next = next; this_index = next; other_index = other.data_[other_index].next; value = other.data_[other_index].value; } data_[this_index].value = end_; // adjust data_not_used_ data_not_used_ += number_delete; if( 2 * data_not_used_ > data_.size() ) collect_garbage(); } // ----------------------------------------------------------------- /*! Assign a set equal to the union of two other sets. \param this_target is the index (in this \c sparse_list object) of the set being assinged. \param this_left is the index (in this \c sparse_list object) of the left operand for the union operation. It is OK for \a this_target and \a this_left to be the same value. \param other_right is the index (in the other \c sparse_list object) of the right operand for the union operation. It is OK for \a this_target and \a other_right to be the same value. \param other is the other \c sparse_list object (which may be the same as this \c sparse_list object). \par Checked Assertions \li this_target < n_set_ \li this_left < n_set_ \li other_right < other.n_set_ */ void binary_union( size_t this_target , size_t this_left , size_t other_right , const sparse_list& other ) { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ ); CPPAD_ASSERT_UNKNOWN( this_left < n_set_ ); CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_ ); CPPAD_ASSERT_UNKNOWN( end_ == other.end() ); // determine if we will delete the original version of the target size_t number_delete = 0; bool delete_target = this_target == this_left; delete_target |= (this == &other) & (this_target == other_right); if( delete_target ) { // number of elements that will be deleted by this operation number_delete = number_elements(this_target); } // value and next for left and right sets size_t left_value = data_[this_left].value; size_t left_next = data_[this_left].next; size_t right_value = other.data_[other_right].value; size_t right_next = other.data_[other_right].next; // merge left and right sets to form new target set size_t current = this_target; while( (left_value < end_) | (right_value < end_) ) { if( left_value == right_value ) { right_value = other.data_[right_next].value; right_next = other.data_[right_next].next; } size_t next = data_.extend(1); data_[current].next = next; if( left_value < right_value ) { data_[current].value = left_value; left_value = data_[left_next].value; left_next = data_[left_next].next; } else { data_[current].value = right_value; right_value = other.data_[right_next].value; right_next = other.data_[right_next].next; } current = next; } data_[current].value = end_; // adjust data_not_used_ data_not_used_ += number_delete; if( 2 * data_not_used_ > data_.size() ) collect_garbage(); } // ----------------------------------------------------------------- /*! Sum over all sets of the number of elements /return The the total number of elements */ size_t number_elements(void) const { size_t i, count; count = 0; for(i = 0; i < n_set_; i++) count += number_elements(i); return count; } // ----------------------------------------------------------------- /*! Fetch n_set for vector of sets object. \return Number of from sets for this vector of sets object */ size_t n_set(void) const { return n_set_; } // ----------------------------------------------------------------- /*! Fetch end for this vector of sets object. \return is the maximum element value plus one (the minimum element value is 0). */ size_t end(void) const { return end_; } }; // Tell pod_vector class that each pair_size_t is plain old data and hence // the corresponding constructor need not be called. template <> inline bool is_pod(void) { return true; } /*! Copy a user vector of sets sparsity pattern to an internal sparse_list object. \tparam VectorSet is a simple vector with elements of type \c std::list. \param internal The input value of sparisty does not matter. Upon return it contains the same sparsity pattern as \c user (or the transposed sparsity pattern). \param user sparsity pattern that we are placing \c internal. \param n_row number of rows in the sparsity pattern in \c user (range dimension). \param n_col number of columns in the sparsity pattern in \c user (domain dimension). \param transpose if true, the sparsity pattern in \c internal is the transpose of the one in \c user. Otherwise it is the same sparsity pattern. */ template void sparsity_user2internal( sparse_list& internal , const VectorSet& user , size_t n_row , size_t n_col , bool transpose ) { CPPAD_ASSERT_UNKNOWN( n_row == size_t(user.size()) ); CPPAD_ASSERT_KNOWN( size_t( user.size() ) == n_row, "Size of this vector of lists sparsity pattern is not equal " "the range dimension for the corresponding function." ); size_t i, j; std::set::const_iterator itr; // transposed pattern case if( transpose ) { internal.resize(n_col, n_row); for(i = 0; i < n_row; i++) { itr = user[i].begin(); while(itr != user[i].end()) { j = *itr++; CPPAD_ASSERT_UNKNOWN( j < n_col ); internal.add_element(j, i); } } return; } // same pattern case internal.resize(n_row, n_col); for(i = 0; i < n_row; i++) { itr = user[i].begin(); while(itr != user[i].end()) { j = *itr++; CPPAD_ASSERT_UNKNOWN( j < n_col ); internal.add_element(i, j); } } return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/bool_fun.hpp0000644000176200001440000001452514536067013020005 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BOOL_FUN_INCLUDED # define CPPAD_BOOL_FUN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin BoolFun$$ $spell namespace bool CppAD const $$ $index bool, AD function$$ $index function, AD bool$$ $index unary, AD bool$$ $index binary, AD bool$$ $section AD Boolean Functions$$ $head Syntax$$ $codei%CPPAD_BOOL_UNARY(%Base%, %unary_name%) %$$ $icode%b% = %unary_name%(%u%) %$$ $icode%b% = %unary_name%(%x%) %$$ $codei%CPPAD_BOOL_BINARY(%Base%, %binary_name%) %$$ $icode%b% = %binary_name%(%u%, %v%) %$$ $icode%b% = %binary_name%(%x%, %y%)%$$ $head Purpose$$ Create a $code bool$$ valued function that has $codei%AD<%Base%>%$$ arguments. $head unary_name$$ This is the name of the $code bool$$ valued function with one argument (as it is used in the source code). The user must provide a version of $icode unary_name$$ where the argument has type $icode Base$$. CppAD uses this to create a version of $icode unary_name$$ where the argument has type $codei%AD<%Base%>%$$. $head u$$ The argument $icode u$$ has prototype $codei% const %Base% &%u% %$$ It is the value at which the user provided version of $icode unary_name$$ is to be evaluated. It is also used for the first argument to the user provided version of $icode binary_name$$. $head x$$ The argument $icode x$$ has prototype $codei% const AD<%Base%> &%x% %$$ It is the value at which the CppAD provided version of $icode unary_name$$ is to be evaluated. It is also used for the first argument to the CppAD provided version of $icode binary_name$$. $head b$$ The result $icode b$$ has prototype $codei% bool %b% %$$ $head Create Unary$$ $index CPPAD_BOOL_UNARY$$ The preprocessor macro invocation $codei% CPPAD_BOOL_UNARY(%Base%, %unary_name%) %$$ defines the version of $icode unary_name$$ with a $codei%AD<%Base%>%$$ argument. This can with in a namespace (not the $code CppAD$$ namespace) but must be outside of any routine. $head binary_name$$ This is the name of the $code bool$$ valued function with two arguments (as it is used in the source code). The user must provide a version of $icode binary_name$$ where the arguments have type $icode Base$$. CppAD uses this to create a version of $icode binary_name$$ where the arguments have type $codei%AD<%Base%>%$$. $head v$$ The argument $icode v$$ has prototype $codei% const %Base% &%v% %$$ It is the second argument to the user provided version of $icode binary_name$$. $head y$$ The argument $icode x$$ has prototype $codei% const AD<%Base%> &%y% %$$ It is the second argument to the CppAD provided version of $icode binary_name$$. $head Create Binary$$ $index CPPAD_BOOL_BINARY$$ The preprocessor macro invocation $codei% CPPAD_BOOL_BINARY(%Base%, %binary_name%) %$$ defines the version of $icode binary_name$$ with $codei%AD<%Base%>%$$ arguments. This can with in a namespace (not the $code CppAD$$ namespace) but must be outside of any routine. $head Operation Sequence$$ The result of this operation is not an $cref/AD of Base/glossary/AD of Base/$$ object. Thus it will not be recorded as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Example$$ $children% example/bool_fun.cpp %$$ The file $cref bool_fun.cpp$$ contains an example and test of these operations. It returns true if it succeeds and false otherwise. $head Deprecated$$ The preprocessor symbols $code CppADCreateUnaryBool$$ and $code CppADCreateBinaryBool$$ are defined to be the same as $code CPPAD_BOOL_UNARY$$ and $code CPPAD_BOOL_BINARY$$ respectively (but their use is deprecated). $end */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file bool_fun.hpp Routines and macros that implement functions from AD to bool. */ /*! Macro that defines a unary function bool F(AD x) using bool F(Base x). \param Base base for the AD type of arguments to this unary bool valued function. \param unary_name name of this unary function; i.e., \c F. */ # define CPPAD_BOOL_UNARY(Base, unary_name) \ inline bool unary_name (const CppAD::AD &x) \ { \ return CppAD::AD::UnaryBool(unary_name, x); \ } /*! Deprecated name for CPPAD_BOOL_UNARY */ # define CppADCreateUnaryBool CPPAD_BOOL_UNARY /*! Link a function name, and AD value pair to function call with base argument and bool retrun value. \param FunName is the name of the function that we are linking. \param x is the argument where we are evaluating the function. */ template inline bool AD::UnaryBool( bool FunName(const Base &x), const AD &x ) { return FunName(x.value_); } /*! Macro that defines a binary function bool F(AD x, AD y) using bool F(Base x, Base y). \param Base base for the AD type of arguments to this binary bool valued function. \param binary_name name of this binary function; i.e., \c F. */ # define CPPAD_BOOL_BINARY(Base, binary_name) \ inline bool binary_name ( \ const CppAD::AD &x, const CppAD::AD &y) \ { \ return CppAD::AD::BinaryBool(binary_name, x, y); \ } /*! Deprecated name for CPPAD_BOOL_BINARY */ # define CppADCreateBinaryBool CPPAD_BOOL_BINARY /*! Link a function name, and two AD values to function call with base arguments and bool retrun value. \param FunName is the name of the function that we are linking. \param x is the first argument where we are evaluating the function at. \param y is the second argument where we are evaluating the function at. */ template inline bool AD::BinaryBool( bool FunName(const Base &x, const Base &y), const AD &x, const AD &y ) { return FunName(x.value_, y.value_); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sub.hpp0000644000176200001440000000523314536067013016767 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SUB_INCLUDED # define CPPAD_SUB_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD operator - (const AD &left , const AD &right) { // compute the Base part AD result; result.value_ = left.value_ - right.value_; CPPAD_ASSERT_UNKNOWN( Parameter(result) ); // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return result; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_left = left.tape_id_ == tape_id; bool var_right = right.tape_id_ == tape_id; if( var_left ) { if( var_right ) { // result = variable - variable CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(left.taddr_, right.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(SubvvOp); // make result a variable result.tape_id_ = tape_id; } else if( IdenticalZero(right.value_) ) { // result = variable - 0 result.make_variable(left.tape_id_, left.taddr_); } else { // result = variable - parameter CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(left.taddr_, p); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(SubvpOp); // make result a variable result.tape_id_ = tape_id; } } else if( var_right ) { // result = parameter - variable CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(left.value_); tape->Rec_.PutArg(p, right.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(SubpvOp); // make result a variable result.tape_id_ = tape_id; } return result; } // convert other cases into the case above CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(-) } // END CppAD namespace # endif TMB/inst/include/cppad/local/cosh_op.hpp0000644000176200001440000001466214536067013017636 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_COSH_OP_INCLUDED # define CPPAD_COSH_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file cosh_op.hpp Forward and reverse mode calculations for z = cosh(x). */ /*! Compute forward mode Taylor coefficient for result of op = CoshOp. The C++ source code corresponding to this operation is \verbatim z = cosh(x) \endverbatim The auxillary result is \verbatim y = sinh(x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_cosh_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* c = taylor + i_z * cap_order; Base* s = c - cap_order; // rest of this routine is identical for the following cases: // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op. // (except that there is a sign difference for hyperbolic case). size_t k; if( p == 0 ) { s[0] = sinh( x[0] ); c[0] = cosh( x[0] ); p++; } for(size_t j = p; j <= q; j++) { s[j] = Base(0); c[j] = Base(0); for(k = 1; k <= j; k++) { s[j] += Base(k) * x[k] * c[j-k]; c[j] += Base(k) * x[k] * s[j-k]; } s[j] /= Base(j); c[j] /= Base(j); } } /*! Compute forward mode Taylor coefficient for result of op = CoshOp. The C++ source code corresponding to this operation is \verbatim z = cosh(x) \endverbatim The auxillary result is \verbatim y = sinh(x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_cosh_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* s = taylor + i_z * num_taylor_per_var; Base* c = s - num_taylor_per_var; // rest of this routine is identical for the following cases: // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op // (except that there is a sign difference for the hyperbolic case). size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { s[m+ell] = Base(q) * x[m + ell] * c[0]; c[m+ell] = Base(q) * x[m + ell] * s[0]; for(size_t k = 1; k < q; k++) { s[m+ell] += Base(k) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell]; c[m+ell] += Base(k) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell]; } s[m+ell] /= Base(q); c[m+ell] /= Base(q); } } /*! Compute zero order forward mode Taylor coefficient for result of op = CoshOp. The C++ source code corresponding to this operation is \verbatim z = cosh(x) \endverbatim The auxillary result is \verbatim y = sinh(x) \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_cosh_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* c = taylor + i_z * cap_order; // called z in documentation Base* s = c - cap_order; // called y in documentation c[0] = cosh( x[0] ); s[0] = sinh( x[0] ); } /*! Compute reverse mode partial derivatives for result of op = CoshOp. The C++ source code corresponding to this operation is \verbatim z = cosh(x) \endverbatim The auxillary result is \verbatim y = sinh(x) \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_cosh_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* c = taylor + i_z * cap_order; // called z in doc Base* pc = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* s = c - cap_order; // called y in documentation Base* ps = pc - nc_partial; // If pc is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pc[i_d]); if( skip ) return; // rest of this routine is identical for the following cases: // reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op. size_t j = d; size_t k; while(j) { ps[j] /= Base(j); pc[j] /= Base(j); for(k = 1; k <= j; k++) { px[k] += ps[j] * Base(k) * c[j-k]; px[k] += pc[j] * Base(k) * s[j-k]; ps[j-k] += pc[j] * Base(k) * x[k]; pc[j-k] += ps[j] * Base(k) * x[k]; } --j; } px[0] += ps[0] * c[0]; px[0] += pc[0] * s[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/epsilon.hpp0000644000176200001440000000313614536067013017647 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_EPSILON_INCLUDED # define CPPAD_EPSILON_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------ $begin epsilon$$ $spell std eps CppAD namespace const $$ $index AD, epsilon$$ $index epsilon, AD$$ $section Machine Epsilon For AD Types$$ $head Deprecated 2012-06-17$$ $index deprecated, epsilon$$ This routine has bee deprecated. You should use the $cref/numeric_limits/limits/$$ $code epsilon$$ instead. $head Syntax$$ $icode%eps% = epsilon<%Float%>()%$$ $head Purpose$$ Obtain the value of machine epsilon corresponding to the type $icode%Float%$$. $head Float$$ this type can either be $codei%AD<%Base%>%$$, or it can be $icode Base$$ for any $codei%AD<%Base%>%$$ type. $head eps$$ The result $icode eps$$ has prototype $codei% %Float% eps %$$ $end ------------------------------------------------------------------------------ */ namespace CppAD { template inline ADtype epsilon(void) { typedef typename ADtype::value_type value_type; return ADtype ( epsilon() ); } } # endif TMB/inst/include/cppad/local/tanh_op.hpp0000644000176200001440000001364614536067013017635 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_TANH_OP_INCLUDED # define CPPAD_TANH_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file tanh_op.hpp Forward and reverse mode calculations for z = tanh(x). */ /*! Compute forward mode Taylor coefficient for result of op = TanOp. The C++ source code corresponding to this operation is \verbatim z = tanh(x) \endverbatim The auxillary result is \verbatim y = tanh(x)^2 \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_tanh_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; Base* y = z - cap_order; size_t k; if( p == 0 ) { z[0] = tanh( x[0] ); y[0] = z[0] * z[0]; p++; } for(size_t j = p; j <= q; j++) { Base base_j = static_cast(j); z[j] = x[j]; for(k = 1; k <= j; k++) z[j] -= Base(k) * x[k] * y[j-k] / base_j; y[j] = z[0] * z[j]; for(k = 1; k <= j; k++) y[j] += z[k] * z[j-k]; } } /*! Multiple directions forward mode Taylor coefficient for op = TanOp. The C++ source code corresponding to this operation is \verbatim z = tanh(x) \endverbatim The auxillary result is \verbatim y = tanh(x)^2 \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_tanh_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; Base* y = z - num_taylor_per_var; size_t k; size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { z[m+ell] = Base(q) * ( x[m+ell] - x[m+ell] * y[0] ); for(k = 1; k < q; k++) z[m+ell] -= Base(k) * x[(k-1)*r+1+ell] * y[(q-k-1)*r+1+ell]; z[m+ell] /= Base(q); // y[m+ell] = Base(2) * z[m+ell] * z[0]; for(k = 1; k < q; k++) y[m+ell] += z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell]; } } /*! Compute zero order forward mode Taylor coefficient for result of op = TanOp. The C++ source code corresponding to this operation is \verbatim z = tanh(x) \endverbatim The auxillary result is \verbatim y = cos(x) \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_tanh_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; // called z in documentation Base* y = z - cap_order; // called y in documentation z[0] = tanh( x[0] ); y[0] = z[0] * z[0]; } /*! Compute reverse mode partial derivatives for result of op = TanOp. The C++ source code corresponding to this operation is \verbatim z = tanh(x) \endverbatim The auxillary result is \verbatim y = cos(x) \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_tanh_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* z = taylor + i_z * cap_order; // called z in doc Base* pz = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* y = z - cap_order; // called y in documentation Base* py = pz - nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; size_t j = d; size_t k; Base base_two(2); while(j) { px[j] += pz[j]; pz[j] /= Base(j); for(k = 1; k <= j; k++) { px[k] -= pz[j] * y[j-k] * Base(k); py[j-k] -= pz[j] * x[k] * Base(k); } for(k = 0; k < j; k++) pz[k] += py[j-1] * z[j-k-1] * base_two; --j; } px[0] += pz[0] * (Base(1) - y[0]); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/pow_op.hpp0000644000176200001440000004027114536067013017502 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_POW_OP_INCLUDED # define CPPAD_POW_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file pow_op.hpp Forward and reverse mode calculations for z = pow(x, y). */ // --------------------------- Powvv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = PowvvOp. In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_pow_op */ template inline void forward_powvv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowvvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // z_0 = log(x) forward_log_op(p, q, i_z, arg[0], cap_order, taylor); // z_1 = z_0 * y addr_t adr[2]; adr[0] = i_z; adr[1] = arg[1]; forward_mulvv_op(p, q, i_z+1, adr, parameter, cap_order, taylor); // z_2 = exp(z_1) // final result for zero order case is exactly the same as for Base if( p == 0 ) { // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z_2 = taylor + (i_z+2) * cap_order; z_2[0] = pow(x[0], y[0]); p++; } if( p <= q ) forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor); } /*! Multiple directions forward mode Taylor coefficients for op = PowvvOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_pow_op_dir */ template inline void forward_powvv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowvvOp) - 1 // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // z_0 = log(x) forward_log_op_dir(q, r, i_z, arg[0], cap_order, taylor); // z_1 = y * z_0 addr_t adr[2]; adr[0] = i_z; adr[1] = arg[1]; forward_mulvv_op_dir(q, r, i_z+1, adr, parameter, cap_order, taylor); // z_2 = exp(z_1) forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor); } /*! Compute zero order forward mode Taylor coefficients for result of op = PowvvOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_pow_op_0 */ template inline void forward_powvv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // NumRes(PowvvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z_0 = taylor + i_z * cap_order; Base* z_1 = z_0 + cap_order; Base* z_2 = z_1 + cap_order; z_0[0] = log( x[0] ); z_1[0] = z_0[0] * y[0]; z_2[0] = pow(x[0], y[0]); } /*! Compute reverse mode partial derivatives for result of op = PowvvOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails reverse_pow_op */ template inline void reverse_powvv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // convert from final result to first result i_z -= 2; // NumRes(PowvvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // z_2 = exp(z_1) reverse_exp_op( d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial ); // z_1 = z_0 * y addr_t adr[2]; adr[0] = i_z; adr[1] = arg[1]; reverse_mulvv_op( d, i_z+1, adr, parameter, cap_order, taylor, nc_partial, partial ); // z_0 = log(x) reverse_log_op( d, i_z, arg[0], cap_order, taylor, nc_partial, partial ); } // --------------------------- Powpv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = PowpvOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_pow_op */ template inline void forward_powpv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowpvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* z_0 = taylor + i_z * cap_order; // z_0 = log(x) Base x = parameter[ arg[0] ]; size_t d; for(d = p; d <= q; d++) { if( d == 0 ) z_0[d] = log(x); else z_0[d] = Base(0); } // z_1 = z_0 * y addr_t adr[2]; // offset of z_i in taylor (as if it were a parameter); i.e., log(x) adr[0] = i_z * cap_order; // offset of y in taylor (as a variable) adr[1] = arg[1]; // Trick: use taylor both for the parameter vector and variable values forward_mulpv_op(p, q, i_z+1, adr, taylor, cap_order, taylor); // z_2 = exp(z_1) // zero order case exactly same as Base type operation if( p == 0 ) { Base* y = taylor + arg[1] * cap_order; Base* z_2 = taylor + (i_z+2) * cap_order; z_2[0] = pow(x, y[0]); p++; } if( p <= q ) forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor); } /*! Multiple directions forward mode Taylor coefficients for op = PowpvOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_pow_op_dir */ template inline void forward_powpv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowpvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* z_0 = taylor + i_z * num_taylor_per_var; // z_0 = log(x) size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) z_0[m+ell] = Base(0); // z_1 = z_0 * y addr_t adr[2]; // offset of z_0 in taylor (as if it were a parameter); i.e., log(x) adr[0] = i_z * num_taylor_per_var; // ofset of y in taylor (as a variable) adr[1] = arg[1]; // Trick: use taylor both for the parameter vector and variable values forward_mulpv_op_dir(q, r, i_z+1, adr, taylor, cap_order, taylor); // z_2 = exp(z_1) forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor); } /*! Compute zero order forward mode Taylor coefficient for result of op = PowpvOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_pow_op_0 */ template inline void forward_powpv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // NumRes(PowpvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 ); // Paraemter value Base x = parameter[ arg[0] ]; // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z_0 = taylor + i_z * cap_order; Base* z_1 = z_0 + cap_order; Base* z_2 = z_1 + cap_order; // z_0 = log(x) z_0[0] = log(x); // z_1 = z_0 * y z_1[0] = z_0[0] * y[0]; // z_2 = exp(z_1) // zero order case exactly same as Base type operation z_2[0] = pow(x, y[0]); } /*! Compute reverse mode partial derivative for result of op = PowpvOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails reverse_pow_op */ template inline void reverse_powpv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // convert from final result to first result i_z -= 2; // NumRes(PowpvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // z_2 = exp(z_1) reverse_exp_op( d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial ); // z_1 = z_0 * y addr_t adr[2]; adr[0] = i_z * cap_order; // offset of z_0[0] in taylor adr[1] = arg[1]; // index of y in taylor and partial // use taylor both for parameter and variable values reverse_mulpv_op( d, i_z+1, adr, taylor, cap_order, taylor, nc_partial, partial ); // z_0 = log(x) // x is a parameter } // --------------------------- Powvp ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = PowvpOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_pow_op */ template inline void forward_powvp_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowvpOp) - 1 // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // z_0 = log(x) forward_log_op(p, q, i_z, arg[0], cap_order, taylor); // z_1 = y * z_0 addr_t adr[2]; adr[0] = arg[1]; adr[1] = i_z; forward_mulpv_op(p, q, i_z+1, adr, parameter, cap_order, taylor); // z_2 = exp(z_1) // zero order case exactly same as Base type operation if( p == 0 ) { Base* z_2 = taylor + (i_z+2) * cap_order; Base* x = taylor + arg[0] * cap_order; Base y = parameter[ arg[1] ]; z_2[0] = pow(x[0], y); p++; } if( p <= q ) forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor); } /*! Multiple directions forward mode Taylor coefficients for op = PowvpOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_pow_op_dir */ template inline void forward_powvp_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowvpOp) - 1 // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // z_0 = log(x) forward_log_op_dir(q, r, i_z, arg[0], cap_order, taylor); // z_1 = y * z_0 addr_t adr[2]; adr[0] = arg[1]; adr[1] = i_z; forward_mulpv_op_dir(q, r, i_z+1, adr, parameter, cap_order, taylor); // z_2 = exp(z_1) forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor); } /*! Compute zero order forward mode Taylor coefficients for result of op = PowvpOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails forward_pow_op_0 */ template inline void forward_powvp_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // NumRes(PowvpOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 ); // Paraemter value Base y = parameter[ arg[1] ]; // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* z_0 = taylor + i_z * cap_order; Base* z_1 = z_0 + cap_order; Base* z_2 = z_1 + cap_order; // z_0 = log(x) z_0[0] = log(x[0]); // z_1 = z_0 * y z_1[0] = z_0[0] * y; // z_2 = exp(z_1) // zero order case exactly same as Base type operation z_2[0] = pow(x[0], y); } /*! Compute reverse mode partial derivative for result of op = PowvpOp. The C++ source code corresponding to this operation is \verbatim z = pow(x, y) \endverbatim In the documentation below, this operations is for the case where x is a variable and y is a parameter. \copydetails reverse_pow_op */ template inline void reverse_powvp_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // convert from final result to first result i_z -= 2; // NumRes(PowvpOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // z_2 = exp(z_1) reverse_exp_op( d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial ); // z_1 = y * z_0 addr_t adr[2]; adr[0] = arg[1]; adr[1] = i_z; reverse_mulpv_op( d, i_z+1, adr, parameter, cap_order, taylor, nc_partial, partial ); // z_0 = log(x) reverse_log_op( d, i_z, arg[0], cap_order, taylor, nc_partial, partial ); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/ad_ctor.hpp0000644000176200001440000001037014536067013017607 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_AD_CTOR_INCLUDED # define CPPAD_AD_CTOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------ $begin ad_ctor$$ $spell cppad ctor initializes Vec const $$ $index AD, constructor$$ $index constructor, AD$$ $index convert, to AD$$ $index Base, convert to AD$$ $index VecAD, convert to AD$$ $section AD Constructors $$ $head Syntax$$ $codei%AD<%Base%> %y%() %$$ $codei%AD<%Base%> %y%(%x%) %$$ $head Purpose$$ creates a new $codei%AD<%Base%>%$$ object $icode y$$ and initializes its value as equal to $icode x$$. $head x$$ $subhead implicit$$ There is an implicit constructor where $icode x$$ has one of the following prototypes: $codei% const %Base%& %x% const VecAD<%Base%>& %x% %$$ $subhead explicit$$ There is an explicit constructor where $icode x$$ has prototype $codei% const %Type%& %x% %$$ for any type that has an explicit constructor of the form $icode%Base%(%x%)%$$. $subhead deprecated$$ $index deprecated, constructor$$ $index constructor, deprecated$$ If you set $cref/cppad_implicit_ctor_from_any_type /cmake /cppad_implicit_ctor_from_any_type /$$ to be $code YES$$ during the install procedure, you will get an implicit constructor with prototype $codei% const %Type%& %x% %$$ for any type that has an explicit constructor of the form $icode%Base%(%x%)%$$. $head y$$ The target $icode y$$ has prototype $codei% AD<%Base%> %y% %$$ $head Example$$ $children% example/ad_ctor.cpp %$$ The files $cref ad_ctor.cpp$$ contain examples and tests of these operations. It test returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------ */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file ad_ctor.hpp AD constructors and and copy operations. */ /*! \page AD_default_ctor Use default copy constructor because they may be optimized better than the code below: \code template inline AD::AD(const AD &x) { value_ = x.value_; tape_id_ = x.tape_id_; taddr_ = x.taddr_; return; } \endcode */ /*! Default Constructor. \tparam Base Base type for this AD object. */ template inline AD::AD(void) : value_() , tape_id_(0) , taddr_(0) { } /*! Constructor from Base type. \tparam Base Base type for this AD object. \param b is the Base type value corresponding to this AD object. The tape identifier will be an invalid tape identifier, so this object is initially a parameter. */ // Disabled by Kasper // template // inline AD::AD(const Base &b) // : value_(b) // , tape_id_(0) // , taddr_(0) // { // check that this is a parameter // CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); // } /*! Constructor from an ADVec element drops the vector information. \tparam Base Base type for this AD object. */ template inline AD::AD(const VecAD_reference &x) { *this = x.ADBase(); } /*! Constructor from any other type, converts to Base type, and uses constructor from Base type. \tparam Base Base type for this AD object. \tparam T is the the type that is being converted to AD. There must be a constructor for Base from Type. \param t is the object that is being converted from T to AD. */ template template inline AD::AD(const T &t) : value_(Base(t)) , tape_id_(0) , taddr_(0) { } // Added by Kasper #define CTOR_FROM(TYPE) \ template \ inline AD::AD(const TYPE &t) \ : value_(Base(t)) \ , tape_id_(0) \ , taddr_(0) \ { } CTOR_FROM(double) #undef CTOR_FROM } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/div.hpp0000644000176200001440000000557714536067013016773 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DIV_INCLUDED # define CPPAD_DIV_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD operator / (const AD &left , const AD &right) { // compute the Base part AD result; result.value_ = left.value_ / right.value_; CPPAD_ASSERT_UNKNOWN( Parameter(result) ); // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return result; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_left = left.tape_id_ == tape_id; bool var_right = right.tape_id_ == tape_id; if( var_left ) { if( var_right ) { // result = variable / variable CPPAD_ASSERT_KNOWN( left.tape_id_ == right.tape_id_, "Dividing AD objects that are" " variables on different tapes." ); CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(left.taddr_, right.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(DivvvOp); // make result a variable result.tape_id_ = tape_id; } else if( IdenticalOne(right.value_) ) { // result = variable / 1 result.make_variable(left.tape_id_, left.taddr_); } else { // result = variable / parameter CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(left.taddr_, p); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(DivvpOp); // make result a variable result.tape_id_ = tape_id; } } else if( var_right ) { if( IdenticalZero(left.value_) ) { // result = 0 / variable } else { // result = parameter / variable CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(left.value_); tape->Rec_.PutArg(p, right.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(DivpvOp); // make result a variable result.tape_id_ = tape_id; } } return result; } // convert other cases into the case above CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(/) } // END CppAD namespace # endif TMB/inst/include/cppad/local/mul.hpp0000644000176200001440000000567514536067013017005 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_MUL_INCLUDED # define CPPAD_MUL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD operator * (const AD &left , const AD &right) { // compute the Base part AD result; result.value_ = left.value_ * right.value_; CPPAD_ASSERT_UNKNOWN( Parameter(result) ); // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return result; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_left = left.tape_id_ == tape_id; bool var_right = right.tape_id_ == tape_id; if( var_left ) { if( var_right ) { // result = variable * variable CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(left.taddr_, right.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(MulvvOp); // make result a variable result.tape_id_ = tape_id; } else if( IdenticalZero(right.value_) ) { // result = variable * 0 } else if( IdenticalOne(right.value_) ) { // result = variable * 1 result.make_variable(left.tape_id_, left.taddr_); } else { // result = variable * parameter CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(p, left.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(MulpvOp); // make result a variable result.tape_id_ = tape_id; } } else if( var_right ) { if( IdenticalZero(left.value_) ) { // result = 0 * variable } else if( IdenticalOne(left.value_) ) { // result = 1 * variable result.make_variable(right.tape_id_, right.taddr_); } else { // result = parameter * variable CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(left.value_); tape->Rec_.PutArg(p, right.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(MulpvOp); // make result a variable result.tape_id_ = tape_id; } } return result; } // convert other cases into the case above CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(*) } // END CppAD namespace # endif TMB/inst/include/cppad/local/fun_eval.hpp0000644000176200001440000000174114536067013017775 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FUN_EVAL_INCLUDED # define CPPAD_FUN_EVAL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin FunEval$$ $spell $$ $index evaluate, ADFun$$ $index ADFun, evaluate$$ $section Evaluate ADFun Functions, Derivatives, and Sparsity Patterns$$ $childtable% omh/forward/forward.omh% omh/reverse/reverse.omh% cppad/local/sparse.hpp %$$ $end */ # include # include # include # endif TMB/inst/include/cppad/local/pod_vector.hpp0000644000176200001440000002401114536067013020335 0ustar liggesusers// $Id:$ # ifndef CPPAD_POD_VECTOR_INCLUDED # define CPPAD_POD_VECTOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # if CPPAD_CSTDINT_HAS_8_TO_64 # include # endif # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file pod_vector.hpp File used to define pod_vector class */ /* A list of which Types pod_vector consideres to be plain old data */ /// default value is false template inline bool is_pod(void) { return false; } /// system pod types so far: template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } # if CPPAD_CSTDINT_HAS_8_TO_64 template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } // template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } # else // CPPAD_CSTDINT_HAS_8_TO_64 template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } // template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } template <> inline bool is_pod(void) { return true; } /* This line: template <> inline bool is_pod(void) { return true; } is a re-definition *if* 'size_t' is equal to 'unsigned int'. To avoid this issue we will assume that 'size_t' is always an alias to one of the unsigned integer types, although this is not guarantied to be correct: http://stackoverflow.com/questions/23749822/is-size-t-guaranteed-to-be-an-alias-type-to-one-of-integer-types FIXME: throw a compile time error if assumption is wrong. */ template <> inline bool is_pod(void) { return true; } # endif // CPPAD_CSTDINT_HAS_8_TO_64 /// CppAD pod types so far: template <> inline bool is_pod(void) { return true; } // --------------------------------------------------------------------------- /*! A vector class with Type element that does not use element constructors or destructors when Type is Plain Old Data (pod). */ template class pod_vector { private: /// maximum number of elements that should ever be in this vector size_t max_length_; /// number of elements currently in this vector size_t length_; /// maximum number of Type elements current allocation can hold size_t capacity_; /// pointer to the first type elements /// (not defined and should not be used when capacity_ = 0) Type *data_; /// do not use the copy constructor explicit pod_vector(const pod_vector& ) { CPPAD_ASSERT_UNKNOWN(false); } public: /// Constructors set capacity, length, and data to zero. /// /// \param max_length /// value for maximum number of elements in this vector. inline pod_vector( size_t max_length = std::numeric_limits::max() ) : max_length_(max_length), length_(0), capacity_(0), data_(CPPAD_NULL) { } // ---------------------------------------------------------------------- /// Destructor: returns allocated memory to \c thread_alloc; /// see \c extend. If this is not plain old data, /// the destructor for each element is called. ~pod_vector(void) { if( capacity_ > 0 ) { void* v_ptr = reinterpret_cast( data_ ); if( ! is_pod() ) { // call destructor for each element size_t i; for(i = 0; i < capacity_; i++) (data_ + i)->~Type(); } thread_alloc::return_memory(v_ptr); } } // ---------------------------------------------------------------------- /// current number of elements in this vector. inline size_t size(void) const { return length_; } /// current capacity (amount of allocated storage) for this vector. inline size_t capacity(void) const { return capacity_; } /// current data pointer, no longer valid after any of the following: /// extend, erase, operator=, and ~pod_vector. /// Take extreem care when using this function. inline Type* data(void) { return data_; } /// const version of \c data pointer inline const Type* data(void) const { return data_; } // ---------------------------------------------------------------------- /*! Increase the number of elements the end of this vector. \param n is the number of elements to add to end of this vector. \return is the number of elements in the vector before \c extend was extended. - If \c Type is plain old data, new elements are not initialized; i.e., their constructor is not called. Otherwise, the constructor is called for each new element. - This is the only routine that allocates memory for \c pod_vector. and it uses thread_alloc for this allocation, hence this determines which thread corresponds to this vector (when in parallel mode). - If the resulting length of the vector would be more than \c max_length_, and \c NDEBUG is not defined, a CPPAD_ASSERT is generated. */ inline size_t extend(size_t n) { size_t old_length = length_; length_ += n; CPPAD_ASSERT_KNOWN( length_ <= max_length_ , "pod_vector.hpp: attempt to create to large a vector.\n" "If Type is CPPAD_TYPE_ADDR_TYPE, tape is too long for Type." ); // check if we can use current memory if( capacity_ >= length_ ) return old_length; // save more old information size_t old_capacity = capacity_; Type* old_data = data_; // get new memory and set capacity size_t length_bytes = length_ * sizeof(Type); size_t capacity_bytes; void* v_ptr = thread_alloc::get_memory(length_bytes, capacity_bytes); capacity_ = capacity_bytes / sizeof(Type); data_ = reinterpret_cast(v_ptr); CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ ); size_t i; if( ! is_pod() ) { // call constructor for each new element for(i = 0; i < capacity_; i++) new(data_ + i) Type(); } // copy old data to new data for(i = 0; i < old_length; i++) data_[i] = old_data[i]; // return old memory to available pool if( old_capacity > 0 ) { v_ptr = reinterpret_cast( old_data ); if( ! is_pod() ) { for(i = 0; i < old_capacity; i++) (old_data + i)->~Type(); } thread_alloc::return_memory(v_ptr); } // return value for extend(n) is the old length return old_length; } // ---------------------------------------------------------------------- /// non-constant element access; i.e., we can change this element value Type& operator[]( /// element index, must be less than length size_t i ) { CPPAD_ASSERT_UNKNOWN( i < length_ ); return data_[i]; } // ---------------------------------------------------------------------- /// constant element access; i.e., we cannot change this element value const Type& operator[]( /// element index, must be less than length size_t i ) const { CPPAD_ASSERT_UNKNOWN( i < length_ ); return data_[i]; } // ---------------------------------------------------------------------- /*! Remove all the elements from this vector but leave the capacity and data pointer as is. */ void erase(void) { length_ = 0; return; } // ---------------------------------------------------------------------- /*! Remove all the elements from this vector and delete its memory. */ void free(void) { if( capacity_ > 0 ) { void* v_ptr = reinterpret_cast( data_ ); if( ! is_pod() ) { // call destructor for each element size_t i; for(i = 0; i < capacity_; i++) (data_ + i)->~Type(); } thread_alloc::return_memory(v_ptr); } data_ = CPPAD_NULL; capacity_ = 0; length_ = 0; } /// vector assignment operator /// If the resulting length of the vector would be more than /// \c max_length_, and \c NDEBUG is not defined, /// a CPPAD_ASSERT is generated. void operator=( /// right hand size of the assingment operation const pod_vector& x ) { size_t i; if( x.length_ <= capacity_ ) { // use existing allocation for this vector length_ = x.length_; CPPAD_ASSERT_KNOWN( length_ <= max_length_ , "pod_vector.hpp: attempt to create to large a vector.\n" "If Type is CPPAD_TYPE_ADDR_TYPE, tape long for Type." ); } else { // free old memory and get new memory of sufficient length if( capacity_ > 0 ) { void* v_ptr = reinterpret_cast( data_ ); if( ! is_pod() ) { // call destructor for each element for(i = 0; i < capacity_; i++) (data_ + i)->~Type(); } thread_alloc::return_memory(v_ptr); } length_ = capacity_ = 0; extend( x.length_ ); } CPPAD_ASSERT_UNKNOWN( length_ == x.length_ ); for(i = 0; i < length_; i++) { data_[i] = x.data_[i]; } } /*! Swap all properties of this vector with another. \param other is the other vector that we are swapping this vector with. */ void swap(pod_vector& other) { std::swap(capacity_, other.capacity_); std::swap(length_, other.length_); std::swap(data_, other.data_); } }; } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/acos_op.hpp0000644000176200001440000001534014536067013017621 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ACOS_OP_INCLUDED # define CPPAD_ACOS_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file acos_op.hpp Forward and reverse mode calculations for z = acos(x). */ /*! Compute forward mode Taylor coefficient for result of op = AcosOp. The C++ source code corresponding to this operation is \verbatim z = acos(x) \endverbatim The auxillary result is \verbatim y = sqrt(1 - x * x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_acos_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; Base* b = z - cap_order; // called y in documentation size_t k; Base uj; if( p == 0 ) { z[0] = acos( x[0] ); uj = Base(1) - x[0] * x[0]; b[0] = sqrt( uj ); p++; } for(size_t j = p; j <= q; j++) { uj = Base(0); for(k = 0; k <= j; k++) uj -= x[k] * x[j-k]; b[j] = Base(0); z[j] = Base(0); for(k = 1; k < j; k++) { b[j] -= Base(k) * b[k] * b[j-k]; z[j] -= Base(k) * z[k] * b[j-k]; } b[j] /= Base(j); z[j] /= Base(j); // b[j] += uj / Base(2); z[j] -= x[j]; // b[j] /= b[0]; z[j] /= b[0]; } } /*! Multiple directions forward mode Taylor coefficient for op = AcosOp. The C++ source code corresponding to this operation is \verbatim z = acos(x) \endverbatim The auxillary result is \verbatim y = sqrt(1 - x * x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_acos_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; Base* b = z - num_taylor_per_var; // called y in documentation size_t k, ell; size_t m = (q-1) * r + 1; for(ell = 0; ell < r; ell ++) { Base uq = - 2.0 * x[m + ell] * x[0]; for(k = 1; k < q; k++) uq -= x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell]; b[m+ell] = Base(0); z[m+ell] = Base(0); for(k = 1; k < q; k++) { b[m+ell] += Base(k) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell]; z[m+ell] += Base(k) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell]; } b[m+ell] = ( uq / Base(2) - b[m+ell] / Base(q) ) / b[0]; z[m+ell] = -( x[m+ell] + z[m+ell] / Base(q) ) / b[0]; } } /*! Compute zero order forward mode Taylor coefficient for result of op = AcosOp. The C++ source code corresponding to this operation is \verbatim z = acos(x) \endverbatim The auxillary result is \verbatim y = sqrt( 1 - x * x ) \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_acos_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; Base* b = z - cap_order; // called y in documentation z[0] = acos( x[0] ); b[0] = sqrt( Base(1) - x[0] * x[0] ); } /*! Compute reverse mode partial derivatives for result of op = AcosOp. The C++ source code corresponding to this operation is \verbatim z = acos(x) \endverbatim The auxillary result is \verbatim y = sqrt( 1 - x * x ) \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_acos_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* z = taylor + i_z * cap_order; Base* pz = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* b = z - cap_order; // called y in documentation Base* pb = pz - nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; // number of indices to access size_t j = d; size_t k; while(j) { // scale partials w.r.t b[j] by 1 / b[0] pb[j] /= b[0]; // scale partials w.r.t z[j] by 1 / b[0] pz[j] /= b[0]; // update partials w.r.t b^0 pb[0] -= pz[j] * z[j] + pb[j] * b[j]; // update partial w.r.t. x^0 px[0] -= pb[j] * x[j]; // update partial w.r.t. x^j px[j] -= pz[j] + pb[j] * x[0]; // further scale partial w.r.t. z[j] by 1 / j pz[j] /= Base(j); for(k = 1; k < j; k++) { // update partials w.r.t b^(j-k) pb[j-k] -= Base(k) * pz[j] * z[k] + pb[j] * b[k]; // update partials w.r.t. x^k px[k] -= pb[j] * x[j-k]; // update partials w.r.t. z^k pz[k] -= pz[j] * Base(k) * b[j-k]; } --j; } // j == 0 case px[0] -= ( pz[0] + pb[0] * x[0]) / b[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/store_op.hpp0000644000176200001440000004007214536067013020030 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_STORE_OP_INCLUDED # define CPPAD_STORE_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file store_op.hpp Changing the current value of a VecAD element. */ /*! Shared documentation for zero order forward implementation of op = StppOp, StpvOp, StvpOp, or StvvOp (not called). The C++ source code corresponding to this operation is \verbatim v[x] = y \endverbatim where v is a VecAD vector, x is an AD object, and y is AD or Base objects. We define the index corresponding to v[x] by \verbatim i_v_x = index_by_ind[ arg[0] + i_vec ] \endverbatim where i_vec is defined under the heading arg[1] below: \tparam Base base type for the operator; i.e., this operation was recorded using AD and computations by this routine are done using type Base. \param i_z is the index corresponding to the previous variable on the tape (only used for error checking). \param arg \n arg[0] \n is the offset of this VecAD vector relative to the beginning of the isvar_by_ind and index_by_ind arrays. \n \n arg[1] \n If this is a StppOp or StpvOp operation (if x is a parameter), i_vec is defined by \verbatim i_vec = arg[1] \endverbatim If this is a StvpOp or StvvOp operation (if x is a variable), i_vec is defined by \verbatim i_vec = floor( taylor[ arg[1] * cap_order + 0 ] ) \endverbatim where floor(c) is the greatest integer less that or equal c. \n \n arg[2] \n index corresponding to the third operand for this operator; i.e. the index corresponding to y. \param num_par is the total number of parameters on the tape (only used for error checking). \param cap_order number of columns in the matrix containing the Taylor coefficients. \param taylor In StvpOp and StvvOp cases, is used to compute the index in the definition of i_vec above. \param isvar_by_ind If y is a varable (StpvOp and StvvOp cases), isvar_by_ind[ arg[0] + i_vec ] is set to true. Otherwise y is a paraemter (StppOp and StvpOp cases) and isvar_by_ind[ arg[0] + i_vec ] is set to false. \param index_by_ind index_by_ind[ arg[0] - 1 ] is the number of elements in the user vector containing this element. The value index_by_ind[ arg[0] + i_vec] is set equal to arg[2]. \par Check User Errors \li Check that the index is with in range; i.e. i_vec < index_by_ind[ arg[0] - 1 ] Note that, if x is a parameter, the corresponding vector index and it does not change. In this case, the error above should be detected during tape recording. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 0 \li 0 < arg[0] \li if y is a parameter, arg[2] < num_par */ template inline void forward_store_op_0( size_t i_z , const addr_t* arg , size_t num_par , size_t cap_order , Base* taylor , bool* isvar_by_ind , size_t* index_by_ind ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Shared documnetation for sparsity operations corresponding to op = StpvOp or StvvOp (not called). The C++ source code corresponding to this operation is \verbatim v[x] = y \endverbatim where v is a VecAD vector, x is an AD object, and y is AD or Base objects. We define the index corresponding to v[x] by \verbatim i_v_x = combined[ arg[0] + i_vec ] \endverbatim where i_vec is defined under the heading \a arg[1] below: \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param op is the code corresponding to this operator; i.e., StpvOp or StvvOp (only used for error checking). \param arg \n \a arg[0] is the offset corresponding to this VecAD vector in the combined array. \n \n \a arg[2] \n The set with index \a arg[2] in \a var_sparsity is the sparsity pattern corresponding to y. (Note that \a arg[2] > 0 because y is a variable.) \param num_combined is the total number of elements in the VecAD address array. \param combined \a combined [ arg[0] - 1 ] is the index of the set in \a vecad_sparsity corresponding to the sparsity pattern for the vector v. We use the notation i_v below which is defined by \verbatim i_v = combined[ \a arg[0] - 1 ] \endverbatim \param var_sparsity The set with index \a arg[2] in \a var_sparsity is the sparsity pattern for y. This is an input for forward mode operations. For reverse mode operations: The sparsity pattern for v is added to the spartisy pattern for y. \param vecad_sparsity The set with index \a i_v in \a vecad_sparsity is the sparsity pattern for v. This is an input for reverse mode operations. For forward mode operations, the sparsity pattern for y is added to the sparsity pattern for the vector v. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 0 \li 0 < \a arg[0] \li \a arg[0] < \a num_combined \li \a arg[2] < \a var_sparsity.n_set() \li i_v < \a vecad_sparsity.n_set() */ template inline void sparse_store_op( OpCode op , const addr_t* arg , size_t num_combined , const size_t* combined , Vector_set& var_sparsity , Vector_set& vecad_sparsity ) { // This routine is only for documentaiton, it should not be used CPPAD_ASSERT_UNKNOWN( false ); } /*! Zero order forward mode implementation of op = StppOp. \copydetails forward_store_op_0 */ template inline void forward_store_pp_op_0( size_t i_z , const addr_t* arg , size_t num_par , size_t cap_order , Base* taylor , bool* isvar_by_ind , size_t* index_by_ind ) { size_t i_vec = arg[1]; // Because the index is a parameter, this indexing error should be // caught and reported to the user when the tape is recording. CPPAD_ASSERT_UNKNOWN( i_vec < index_by_ind[ arg[0] - 1 ] ); CPPAD_ASSERT_UNKNOWN( NumArg(StppOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(StppOp) == 0 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); isvar_by_ind[ arg[0] + i_vec ] = false; index_by_ind[ arg[0] + i_vec ] = arg[2]; } /*! Zero order forward mode implementation of op = StpvOp. \copydetails forward_store_op_0 */ template inline void forward_store_pv_op_0( size_t i_z , const addr_t* arg , size_t num_par , size_t cap_order , Base* taylor , bool* isvar_by_ind , size_t* index_by_ind ) { size_t i_vec = arg[1]; // Because the index is a parameter, this indexing error should be // caught and reported to the user when the tape is recording. CPPAD_ASSERT_UNKNOWN( i_vec < index_by_ind[ arg[0] - 1 ] ); CPPAD_ASSERT_UNKNOWN( NumArg(StpvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(StpvOp) == 0 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); isvar_by_ind[ arg[0] + i_vec ] = true; index_by_ind[ arg[0] + i_vec ] = arg[2]; } /*! Zero order forward mode implementation of op = StvpOp. \copydetails forward_store_op_0 */ template inline void forward_store_vp_op_0( size_t i_z , const addr_t* arg , size_t num_par , size_t cap_order , Base* taylor , bool* isvar_by_ind , size_t* index_by_ind ) { size_t i_vec = Integer( taylor[ arg[1] * cap_order + 0 ] ); CPPAD_ASSERT_KNOWN( i_vec < index_by_ind[ arg[0] - 1 ] , "VecAD: index during zero order forward sweep is out of range" ); CPPAD_ASSERT_UNKNOWN( NumArg(StvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(StvpOp) == 0 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); isvar_by_ind[ arg[0] + i_vec ] = false; index_by_ind[ arg[0] + i_vec ] = arg[2]; } /*! Zero order forward mode implementation of op = StvvOp. \copydetails forward_store_op_0 */ template inline void forward_store_vv_op_0( size_t i_z , const addr_t* arg , size_t num_par , size_t cap_order , Base* taylor , bool* isvar_by_ind , size_t* index_by_ind ) { size_t i_vec = Integer( taylor[ arg[1] * cap_order + 0 ] ); CPPAD_ASSERT_KNOWN( i_vec < index_by_ind[ arg[0] - 1 ] , "VecAD: index during zero order forward sweep is out of range" ); CPPAD_ASSERT_UNKNOWN( NumArg(StvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(StvpOp) == 0 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); isvar_by_ind[ arg[0] + i_vec ] = true; index_by_ind[ arg[0] + i_vec ] = arg[2]; } /*! Forward mode sparsity operations for StpvOp and StvvOp \copydetails sparse_store_op */ template inline void forward_sparse_store_op( OpCode op , const addr_t* arg , size_t num_combined , const size_t* combined , Vector_set& var_sparsity , Vector_set& vecad_sparsity ) { CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); size_t i_v = combined[ arg[0] - 1 ]; CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < var_sparsity.n_set() ); vecad_sparsity.binary_union(i_v, i_v, arg[2], var_sparsity); return; } /*! Reverse mode sparsity operations for StpvOp and StvvOp This routine is given the sparsity patterns for G(v[x], y , w , u ... ) and it uses them to compute the sparsity patterns for \verbatim H(y , w , u , ... ) = G[ v[x], y , w , u , ... ] \endverbatim The C++ source code corresponding to this operation is \verbatim v[x] = y \endverbatim where v is a VecAD vector, x is an AD object, and y is AD or Base objects. We define the index corresponding to v[x] by \verbatim i_v_x = combined[ arg[0] + i_vec ] \endverbatim where i_vec is defined under the heading \a arg[1] below: \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param op is the code corresponding to this operator; i.e., StpvOp or StvvOp (only used for error checking). \param arg \n \a arg[0] is the offset corresponding to this VecAD vector in the combined array. \n \n \a arg[2] \n The set with index \a arg[2] in \a var_sparsity is the sparsity pattern corresponding to y. (Note that \a arg[2] > 0 because y is a variable.) \param num_combined is the total number of elements in the VecAD address array. \param combined \a combined [ arg[0] - 1 ] is the index of the set in \a vecad_sparsity corresponding to the sparsity pattern for the vector v. We use the notation i_v below which is defined by \verbatim i_v = combined[ \a arg[0] - 1 ] \endverbatim \param var_sparsity The set with index \a arg[2] in \a var_sparsity is the sparsity pattern for y. This is an input for forward mode operations. For reverse mode operations: The sparsity pattern for v is added to the spartisy pattern for y. \param vecad_sparsity The set with index \a i_v in \a vecad_sparsity is the sparsity pattern for v. This is an input for reverse mode operations. For forward mode operations, the sparsity pattern for y is added to the sparsity pattern for the vector v. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 0 \li 0 < \a arg[0] \li \a arg[0] < \a num_combined \li \a arg[2] < \a var_sparsity.n_set() \li i_v < \a vecad_sparsity.n_set() */ template inline void reverse_sparse_jacobian_store_op( OpCode op , const addr_t* arg , size_t num_combined , const size_t* combined , Vector_set& var_sparsity , Vector_set& vecad_sparsity ) { CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); size_t i_v = combined[ arg[0] - 1 ]; CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < var_sparsity.n_set() ); var_sparsity.binary_union(arg[2], arg[2], i_v, vecad_sparsity); return; } /*! Reverse mode sparsity operations for StpvOp and StvvOp This routine is given the sparsity patterns for G(v[x], y , w , u ... ) and it uses them to compute the sparsity patterns for \verbatim H(y , w , u , ... ) = G[ v[x], y , w , u , ... ] \endverbatim The C++ source code corresponding to this operation is \verbatim v[x] = y \endverbatim where v is a VecAD vector, x is an AD object, and y is AD or Base objects. We define the index corresponding to v[x] by \verbatim i_v_x = combined[ arg[0] + i_vec ] \endverbatim where i_vec is defined under the heading \a arg[1] below: \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param op is the code corresponding to this operator; i.e., StpvOp or StvvOp (only used for error checking). \param arg \n \a arg[0] is the offset corresponding to this VecAD vector in the combined array. \n \n \a arg[2] \n The set with index \a arg[2] in \a var_sparsity is the sparsity pattern corresponding to y. (Note that \a arg[2] > 0 because y is a variable.) \param num_combined is the total number of elements in the VecAD address array. \param combined \a combined [ arg[0] - 1 ] is the index of the set in \a vecad_sparsity corresponding to the sparsity pattern for the vector v. We use the notation i_v below which is defined by \verbatim i_v = combined[ \a arg[0] - 1 ] \endverbatim \param var_sparsity The set with index \a arg[2] in \a var_sparsity is the sparsity pattern for y. This is an input for forward mode operations. For reverse mode operations: The sparsity pattern for v is added to the spartisy pattern for y. \param vecad_sparsity The set with index \a i_v in \a vecad_sparsity is the sparsity pattern for v. This is an input for reverse mode operations. For forward mode operations, the sparsity pattern for y is added to the sparsity pattern for the vector v. \par Checked Assertions \li NumArg(op) == 3 \li NumRes(op) == 0 \li 0 < \a arg[0] \li \a arg[0] < \a num_combined \li \a arg[2] < \a var_sparsity.n_set() \li i_v < \a vecad_sparsity.n_set() \param var_jacobian \a var_jacobian[ \a arg[2] ] is false (true) if the Jacobian of G with respect to y is always zero (may be non-zero). \param vecad_jacobian \a vecad_jacobian[i_v] is false (true) if the Jacobian with respect to x is always zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. */ template inline void reverse_sparse_hessian_store_op( OpCode op , const addr_t* arg , size_t num_combined , const size_t* combined , Vector_set& var_sparsity , Vector_set& vecad_sparsity , bool* var_jacobian , bool* vecad_jacobian ) { CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); size_t i_v = combined[ arg[0] - 1 ]; CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < var_sparsity.n_set() ); var_sparsity.binary_union(arg[2], arg[2], i_v, vecad_sparsity); var_jacobian[ arg[2] ] |= vecad_jacobian[i_v]; return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/pow.hpp0000644000176200001440000001622114536067013017002 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_POW_INCLUDED # define CPPAD_POW_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin pow$$ $spell Vec std namespace CppAD const $$ $index pow, AD$$ $index exponent, AD function$$ $section The AD Power Function$$ $head Syntax$$ $icode%z% = pow(%x%, %y%)%$$ $head See Also$$ $cref pow_int$$ $head Purpose$$ Determines the value of the power function which is defined by $latex \[ {\rm pow} (x, y) = x^y \] $$ This version of the $code pow$$ function may use logarithms and exponentiation to compute derivatives. This will not work if $icode x$$ is less than or equal zero. If the value of $icode y$$ is an integer, the $cref pow_int$$ function is used to compute this value using only multiplication (and division if $icode y$$ is negative). (This will work even if $icode x$$ is less than or equal zero.) $head x$$ The argument $icode x$$ has one of the following prototypes $codei% const %Base%& %x% const AD<%Base%>& %x% const VecAD<%Base%>::reference& %x% %$$ $head y$$ The argument $icode y$$ has one of the following prototypes $codei% const %Base%& %y% const AD<%Base%>& %y% const VecAD<%Base%>::reference& %y% %$$ $head z$$ If both $icode x$$ and $icode y$$ are $icode Base$$ objects, the result $icode z$$ is also a $icode Base$$ object. Otherwise, it has prototype $codei% AD<%Base%> %z% %$$ $head Operation Sequence$$ This is an AD of $icode Base$$ $cref/atomic operation/glossary/Operation/Atomic/$$ and hence is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Example$$ $children% example/pow.cpp %$$ The file $cref pow.cpp$$ is an examples and tests of this function. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { // case where x and y are AD ----------------------------------------- template AD pow(const AD& x, const AD& y) { // compute the Base part AD result; result.value_ = pow(x.value_, y.value_); CPPAD_ASSERT_UNKNOWN( Parameter(result) ); // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return result; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_x = x.tape_id_ == tape_id; bool var_y = y.tape_id_ == tape_id; if( var_x ) { if( var_y ) { // result = variable^variable CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(x.taddr_, y.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(PowvvOp); // make result a variable result.tape_id_ = tape_id; } else if( IdenticalZero( y.value_ ) ) { // result = variable^0 } else { // result = variable^parameter CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(y.value_); tape->Rec_.PutArg(x.taddr_, p); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(PowvpOp); // make result a variable result.tape_id_ = tape_id; } } else if( var_y ) { if( IdenticalZero(x.value_) ) { // result = 0^variable } else { // result = variable^parameter CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(x.value_); tape->Rec_.PutArg(p, y.taddr_); // put operator in the tape result.taddr_ = tape->Rec_.PutOp(PowpvOp); // make result a variable result.tape_id_ = tape_id; } } return result; } // ========================================================================= // Fold operations in same way as CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op) // ------------------------------------------------------------------------- // Operations with VecAD_reference and AD only template AD pow(const AD& x, const VecAD_reference& y) { return pow(x, y.ADBase()); } template AD pow(const VecAD_reference& x, const VecAD_reference& y) { return pow(x.ADBase(), y.ADBase()); } template AD pow(const VecAD_reference& x, const AD& y) { return pow(x.ADBase(), y); } // ------------------------------------------------------------------------- // Operations with Base template AD pow(const Base& x, const AD& y) { return pow(AD(x), y); } template AD pow(const Base& x, const VecAD_reference& y) { return pow(AD(x), y.ADBase()); } template AD pow(const AD& x, const Base& y) { return pow(x, AD(y)); } template AD pow(const VecAD_reference& x, const Base& y) { return pow(x.ADBase(), AD(y)); } // ------------------------------------------------------------------------- // Operations with double template AD pow(const double& x, const AD& y) { return pow(AD(x), y); } template AD pow(const double& x, const VecAD_reference& y) { return pow(AD(x), y.ADBase()); } template AD pow(const AD& x, const double& y) { return pow(x, AD(y)); } template AD pow(const VecAD_reference& x, const double& y) { return pow(x.ADBase(), AD(y)); } // ------------------------------------------------------------------------- // Special case to avoid ambuigity when Base is double inline AD pow(const double& x, const AD& y) { return pow(AD(x), y); } inline AD pow(const double& x, const VecAD_reference& y) { return pow(AD(x), y.ADBase()); } inline AD pow(const AD& x, const double& y) { return pow(x, AD(y)); } inline AD pow(const VecAD_reference& x, const double& y) { return pow(x.ADBase(), AD(y)); } // ========================================================================= // Fold operations for the cases where x is an int, // but let cppad/pow_int.hpp handle the cases where y is an int. // ------------------------------------------------------------------------- template AD pow (const int& x, const VecAD_reference& y) { return pow(AD(x), y.ADBase()); } template AD pow (const int& x, const AD& y) { return pow(AD(x), y); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/add_eq.hpp0000644000176200001440000000514514536067013017415 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ADD_EQ_INCLUDED # define CPPAD_ADD_EQ_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD& AD::operator += (const AD &right) { // compute the Base part Base left; left = value_; value_ += right.value_; // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return *this; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_left = tape_id_ == tape_id; bool var_right = right.tape_id_ == tape_id; if( var_left ) { if( var_right ) { // this = variable + variable CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(taddr_, right.taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(AddvvOp); // make this a variable CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id ); } else if( ! IdenticalZero( right.value_ ) ) { // this = variable + parameter // = parameter + variable CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(p, taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(AddpvOp); // make this a variable CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id ); } } else if( var_right ) { if( IdenticalZero(left) ) { // this = 0 + right make_variable(right.tape_id_, right.taddr_); } else { // this = parameter + variable CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(left); tape->Rec_.PutArg(p, right.taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(AddpvOp); // make this a variable tape_id_ = tape_id; } } return *this; } CPPAD_FOLD_ASSIGNMENT_OPERATOR(+=) } // END CppAD namespace # endif TMB/inst/include/cppad/local/identical.hpp0000644000176200001440000000630614536067013020134 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_IDENTICAL_INCLUDED # define CPPAD_IDENTICAL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file identical.hpp Check if certain properties is true for any possible AD tape play back. */ // --------------------------------------------------------------------------- /*! Determine if an AD object is a parameter, and could never have a different value during any tape playback. An AD object \c x is identically a parameter if and only if all of the objects in the following chain are parameters: \code x , x.value , x.value.value , ... \endcode In such a case, the value of the object will always be the same no matter what the independent variable values are at any level. \param x values that we are checking for identically a pamameter. \return returns true iff \c x is identically a parameter. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool IdenticalPar(const AD &x) { return Parameter(x) && IdenticalPar(x.value_); } // Zero ============================================================== /*! Determine if an AD is equal to zero, and must be equal zero during any tape playback. \param x object that we are checking. \return returns true if and only if \c x is equals zero and is identically a parameter \ref IdenticalPar. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool IdenticalZero(const AD &x) { return Parameter(x) && IdenticalZero(x.value_); } // One ============================================================== /*! Determine if an AD is equal to one, and must be equal one during any tape playback. \param x object that we are checking. \return returns true if and only if \c x is equals one and is identically a parameter \ref IdenticalPar. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool IdenticalOne(const AD &x) { return Parameter(x) && IdenticalOne(x.value_); } // Equal =================================================================== /*! Determine if two AD objects are equal, and must be equal during any tape playback. \param x first of two objects we are checking for equal. \param y second of two objects we are checking for equal. \return returns true if and only if the arguments are equal and both identically parameters \ref IdenticalPar. */ template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool IdenticalEqualPar (const AD &x, const AD &y) { bool parameter; parameter = ( Parameter(x) && Parameter(y) ); return parameter && IdenticalEqualPar(x.value_, y.value_); } // ========================================================================== } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sparse_jacobian.hpp0000644000176200001440000007366414536067013021336 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_JACOBIAN_INCLUDED # define CPPAD_SPARSE_JACOBIAN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // maximum number of sparse directions to compute at the same time // # define CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION 1 # define CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION 64 /* $begin sparse_jacobian$$ $spell cppad colpack cmake recomputed valarray std CppAD Bool jac Jacobian const Taylor $$ $section Sparse Jacobian: Easy Driver$$ $index SparseJacobian$$ $index jacobian, sparse$$ $head Syntax$$ $icode%jac% = %f%.SparseJacobian(%x%) %jac% = %f%.SparseJacobian(%x%, %p%) %n_sweep% = %f%.SparseJacobianForward(%x%, %p%, %row%, %col%, %jac%, %work%) %n_sweep% = %f%.SparseJacobianReverse(%x%, %p%, %row%, %col%, %jac%, %work%) %$$ $head Purpose$$ We use $latex n$$ for the $cref/domain/seq_property/Domain/$$ size, and $latex m$$ for the $cref/range/seq_property/Range/$$ size of $icode f$$. We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ do denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. The syntax above sets $icode jac$$ to the Jacobian $latex \[ jac = F^{(1)} (x) \] $$ This routine takes advantage of the sparsity of the Jacobian in order to reduce the amount of computation necessary. If $icode row$$ and $icode col$$ are present, it also takes advantage of the reduced set of elements of the Jacobian that need to be computed. One can use speed tests (e.g. $cref speed_test$$) to verify that results are computed faster than when using the routine $cref Jacobian$$. $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/Uses Forward/sparse_jacobian/Uses Forward/$$ below). $head x$$ The argument $icode x$$ has prototype $codei% const %VectorBase%& %x% %$$ (see $cref/VectorBase/sparse_jacobian/VectorBase/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies that point at which to evaluate the Jacobian. $head p$$ The argument $icode p$$ is optional and has prototype $codei% const %VectorSet%& %p% %$$ (see $cref/VectorSet/sparse_jacobian/VectorSet/$$ below). If it has elements of type $code bool$$, its size is $latex m * n$$. If it has elements of type $code std::set$$, its size is $latex m$$ and all its set elements are between zero and $latex n - 1$$. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the Jacobian $latex F^{(1)} (x)$$. $pre $$ If this sparsity pattern does not change between calls to $codei SparseJacobian$$, it should be faster to calculate $icode p$$ once (using $cref ForSparseJac$$ or $cref RevSparseJac$$) and then pass $icode p$$ to $codei SparseJacobian$$. In addition, if you specify $icode p$$, CppAD will use the same type of sparsity representation (vectors of $code bool$$ or vectors of $code std::set$$) for its internal calculations. Otherwise, the representation for the internal calculations is unspecified. $head row, col$$ The arguments $icode row$$ and $icode col$$ are optional and have prototype $codei% const %VectorSize%& %row% const %VectorSize%& %col% %$$ (see $cref/VectorSize/sparse_jacobian/VectorSize/$$ below). They specify which rows and columns of $latex F^{(1)} (x)$$ are computes and in what order. Not all the non-zero entries in $latex F^{(1)} (x)$$ need be computed, but all the entries specified by $icode row$$ and $icode col$$ must be possibly non-zero in the sparsity pattern. We use $latex K$$ to denote the value $icode%jac%.size()%$$ which must also equal the size of $icode row$$ and $icode col$$. Furthermore, for $latex k = 0 , \ldots , K-1$$, it must hold that $latex row[k] < m$$ and $latex col[k] < n$$. $head jac$$ The result $icode jac$$ has prototype $codei% %VectorBase%& %jac% %$$ In the case where the arguments $icode row$$ and $icode col$$ are not present, the size of $icode jac$$ is $latex m * n$$ and for $latex i = 0 , \ldots , m-1$$, $latex j = 0 , \ldots , n-1$$, $latex \[ jac [ i * n + j ] = \D{ F_i }{ x_j } (x) \] $$ $pre $$ In the case where the arguments $icode row$$ and $icode col$$ are present, we use $latex K$$ to denote the size of $icode jac$$. The input value of its elements does not matter. Upon return, for $latex k = 0 , \ldots , K - 1$$, $latex \[ jac [ k ] = \D{ F_i }{ x_j } (x) \; , \; \; {\rm where} \; i = row[k] \; {\rm and } \; j = col[k] \] $$ $head work$$ If this argument is present, it has prototype $codei% sparse_jacobian_work& %work% %$$ This object can only be used with the routines $code SparseJacobianForward$$ and $code SparseJacobianReverse$$. During its the first use, information is stored in $icode work$$. This is used to reduce the work done by future calls to the same mode (forward or reverse), the same $icode f$$, $icode p$$, $icode row$$, and $icode col$$. If a future call is for a different mode, or any of these values have changed, you must first call $icode%work%.clear()%$$ to inform CppAD that this information needs to be recomputed. $subhead color_method$$ The coloring algorithm determines which columns (forward mode) or rows (reverse mode) can be computed during the same sweep. This field has prototype $codep% std::string %work%.color_method %$$ and its default value (after a constructor or $code clear()$$) is $code "cppad"$$. If $cref colpack_prefix$$ is specified on the $cref/cmake command/cmake/CMake Command/$$ line, you can set this method to $code "colpack"$$. This value only matters on the first call to $code sparse_jacobian$$ that follows the $icode work$$ constructor or a call to $icode%work%.clear()%$$. $head n_sweep$$ The return value $icode n_sweep$$ has prototype $codei% size_t %n_sweep% %$$ If $code SparseJacobianForward$$ ($code SparseJacobianReverse$$) is used, $icode n_sweep$$ is the number of first order forward (reverse) sweeps used to compute the requested Jacobian values. (This is also the number of colors determined by the coloring method mentioned above). This is proportional to the total work that $code SparseJacobian$$ does, not counting the zero order forward sweep, or the work to combine multiple columns (rows) into a single sweep. $head VectorBase$$ The type $icode VectorBase$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Base$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head VectorSet$$ The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code bool$$ or $code std::set$$; see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion of the difference. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $subhead Restrictions$$ If $icode VectorSet$$ has elements of $code std::set$$, then $icode%p%[%i%]%$$ must return a reference (not a copy) to the corresponding set. According to section 26.3.2.3 of the 1998 C++ standard, $code std::valarray< std::set >$$ does not satisfy this condition. $head VectorSize$$ The type $icode VectorSize$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code size_t$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Uses Forward$$ After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After a call to any of the sparse Jacobian routines, the zero order Taylor coefficients correspond to $icode%f%.Forward(0, %x%)%$$ and the other coefficients are unspecified. After $code SparseJacobian$$, the previous calls to $cref Forward$$ are undefined. $head Example$$ $children% example/sparse_jacobian.cpp %$$ The routine $cref sparse_jacobian.cpp$$ is examples and tests of $code sparse_jacobian$$. It return $code true$$, if it succeeds and $code false$$ otherwise. $end ============================================================================== */ # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sparse_jacobian.hpp Sparse Jacobian driver routine and helper functions. */ // =========================================================================== /*! class used by SparseJacobian to hold information so it does not need to be recomputed. */ class sparse_jacobian_work { public: /// Coloring method: "cppad", or "colpack" /// (this field is set by user) std::string color_method; /// indices that sort the user row and col arrays by color CppAD::vector order; /// results of the coloring algorithm CppAD::vector color; /// constructor sparse_jacobian_work(void) : color_method("cppad") { } /// reset coloring method to its default and /// inform CppAD that color and order need to be recomputed void clear(void) { color_method = "cppad"; order.clear(); color.clear(); } }; // =========================================================================== /*! Private helper function forward mode cases \tparam Base is the base type for the recording that is stored in this ADFun object. \tparam VectorBase is a simple vector class with elements of type \a Base. \tparam VectorSet is either \c sparse_pack, \c sparse_set or \c sparse_list. \tparam VectorSize is a simple vector class with elements of type \c size_t. \param x [in] is a vector specifing the point at which to compute the Jacobian. \param p_transpose [in] If work.color.size() != 0, then \c p_transpose is not used. Otherwise, it is a sparsity pattern for the transpose of the Jacobian of this ADFun object. Note that we do not change the values in \c p_transpose, but is not \c const because we use its iterator facility. \param row [in] is the vector of row indices for the returned Jacobian values. \param col [in] is the vector of columns indices for the returned Jacobian values. It must have the same size as \c row. \param jac [out] is the vector of Jacobian values. We use \c K to denote the size of \c jac. The return value jac[k] is the partial of the row[k] range component of the function with respect the the col[k] domain component of its argument. \param work work.color_method is an input. The rest of this structure contains information that is computed by \c SparseJacobainFor. If the sparsity pattern, \c row vector, or \c col vectors are not the same between calls to \c SparseJacobianFor, \c work.clear() must be called to reinitialize \c work. \return Is the number of first order forward sweeps used to compute the requested Jacobian values. The total work, not counting the zero order forward sweep, or the time to combine computations, is proportional to this return value. */ template template size_t ADFun::SparseJacobianFor( const VectorBase& x , VectorSet& p_transpose , const VectorSize& row , const VectorSize& col , VectorBase& jac , sparse_jacobian_work& work ) { size_t j, k, ell; CppAD::vector& order(work.order); CppAD::vector& color(work.color); size_t m = Range(); size_t n = Domain(); // some values const Base zero(0); const Base one(1); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == n ); CPPAD_ASSERT_UNKNOWN( color.size() == 0 || color.size() == n ); // number of components of Jacobian that are required size_t K = size_t(jac.size()); CPPAD_ASSERT_UNKNOWN( row.size() == K ); CPPAD_ASSERT_UNKNOWN( col.size() == K ); // Point at which we are evaluating the Jacobian Forward(0, x); // check for case where nothing (except Forward above) to do if( K == 0 ) return 0; if( color.size() == 0 ) { CPPAD_ASSERT_UNKNOWN( p_transpose.n_set() == n ); CPPAD_ASSERT_UNKNOWN( p_transpose.end() == m ); // execute coloring algorithm color.resize(n); if( work.color_method == "cppad" ) color_general_cppad(p_transpose, col, row, color); else if( work.color_method == "colpack" ) { # if CPPAD_HAS_COLPACK color_general_colpack(p_transpose, col, row, color); # else CPPAD_ASSERT_KNOWN( false, "SparseJacobianForward: work.color_method = colpack " "and colpack_prefix missing from cmake command line." ); # endif } else CPPAD_ASSERT_KNOWN( false, "SparseJacobianForward: work.color_method is not valid." ); // put sorting indices in color order VectorSize key(K); order.resize(K); for(k = 0; k < K; k++) key[k] = color[ col[k] ]; index_sort(key, order); } size_t n_color = 1; for(j = 0; j < n; j++) if( color[j] < n ) n_color = std::max(n_color, color[j] + 1); // initialize the return value for(k = 0; k < K; k++) jac[k] = zero; # if CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION == 1 // direction vector and return values for calls to forward VectorBase dx(n), dy(m); // loop over colors k = 0; for(ell = 0; ell < n_color; ell++) { CPPAD_ASSERT_UNKNOWN( color[ col[ order[k] ] ] == ell ); // combine all columns with this color for(j = 0; j < n; j++) { dx[j] = zero; if( color[j] == ell ) dx[j] = one; } // call forward mode for all these columns at once dy = Forward(1, dx); // set the corresponding components of the result while( k < K && color[ col[order[k]] ] == ell ) { jac[ order[k] ] = dy[row[order[k]]]; k++; } } # else // abbreviation for this value size_t max_r = CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION; CPPAD_ASSERT_UNKNOWN( max_r > 1 ); // count the number of colors done so far size_t count_color = 0; // count the sparse matrix entries done so far k = 0; while( count_color < n_color ) { // number of colors we will do this time size_t r = std::min(max_r , n_color - count_color); VectorBase dx(n * r), dy(m * r); // loop over colors we will do this tme for(ell = 0; ell < r; ell++) { // combine all columns with this color for(j = 0; j < n; j++) { dx[j * r + ell] = zero; if( color[j] == ell + count_color ) dx[j * r + ell] = one; } } size_t q = 1; dy = Forward(q, r, dx); // store results for(ell = 0; ell < r; ell++) { // set the components of the result for this color while( k < K && color[ col[order[k]] ] == ell + count_color ) { jac[ order[k] ] = dy[ row[order[k]] * r + ell ]; k++; } } count_color += r; } # endif return n_color; } /*! Private helper function for reverse mode cases. \tparam Base is the base type for the recording that is stored in this ADFun object. \tparam VectorBase is a simple vector class with elements of type \a Base. \tparam VectorSet is either \c sparse_pack, \c sparse_set or \c sparse_list. \tparam VectorSize is a simple vector class with elements of type \c size_t. \param x [in] is a vector specifing the point at which to compute the Jacobian. \param p [in] If work.color.size() != 0, then \c p is not used. Otherwise, it is a sparsity pattern for the Jacobian of this ADFun object. Note that we do not change the values in \c p, but is not \c const because we use its iterator facility. \param row [in] is the vector of row indices for the returned Jacobian values. \param col [in] is the vector of columns indices for the returned Jacobian values. It must have the same size as \c row. \param jac [out] is the vector of Jacobian values. It must have the same size as \c row. The return value jac[k] is the partial of the row[k] range component of the function with respect the the col[k] domain component of its argument. \param work work.color_method is an input. The rest of This structure contains information that is computed by \c SparseJacobainRev. If the sparsity pattern, \c row vector, or \c col vectors are not the same between calls to \c SparseJacobianRev, \c work.clear() must be called to reinitialize \c work. \return Is the number of first order reverse sweeps used to compute the reverse Jacobian values. The total work, not counting the zero order forward sweep, or the time to combine computations, is proportional to this return value. */ template template size_t ADFun::SparseJacobianRev( const VectorBase& x , VectorSet& p , const VectorSize& row , const VectorSize& col , VectorBase& jac , sparse_jacobian_work& work ) { size_t i, k, ell; CppAD::vector& order(work.order); CppAD::vector& color(work.color); size_t m = Range(); size_t n = Domain(); // some values const Base zero(0); const Base one(1); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == n ); CPPAD_ASSERT_UNKNOWN (color.size() == m || color.size() == 0 ); // number of components of Jacobian that are required size_t K = size_t(jac.size()); CPPAD_ASSERT_UNKNOWN( row.size() == K ); CPPAD_ASSERT_UNKNOWN( col.size() == K ); // Point at which we are evaluating the Jacobian Forward(0, x); // check for case where nothing (except Forward above) to do if( K == 0 ) return 0; if( color.size() == 0 ) { CPPAD_ASSERT_UNKNOWN( p.n_set() == m ); CPPAD_ASSERT_UNKNOWN( p.end() == n ); // execute the coloring algorithm color.resize(m); if( work.color_method == "cppad" ) color_general_cppad(p, row, col, color); else if( work.color_method == "colpack" ) { # if CPPAD_HAS_COLPACK color_general_colpack(p, row, col, color); # else CPPAD_ASSERT_KNOWN( false, "SparseJacobianReverse: work.color_method = colpack " "and colpack_prefix missing from cmake command line." ); # endif } else CPPAD_ASSERT_KNOWN( false, "SparseJacobianReverse: work.color_method is not valid." ); // put sorting indices in color order VectorSize key(K); order.resize(K); for(k = 0; k < K; k++) key[k] = color[ row[k] ]; index_sort(key, order); } size_t n_color = 1; for(i = 0; i < m; i++) if( color[i] < m ) n_color = std::max(n_color, color[i] + 1); // weighting vector for calls to reverse VectorBase w(m); // location for return values from Reverse VectorBase dw(n); // initialize the return value for(k = 0; k < K; k++) jac[k] = zero; // loop over colors k = 0; for(ell = 0; ell < n_color; ell++) { CPPAD_ASSERT_UNKNOWN( color[ row[ order[k] ] ] == ell ); // combine all the rows with this color for(i = 0; i < m; i++) { w[i] = zero; if( color[i] == ell ) w[i] = one; } // call reverse mode for all these rows at once dw = Reverse(1, w); // set the corresponding components of the result while( k < K && color[ row[order[k]] ] == ell ) { jac[ order[k] ] = dw[col[order[k]]]; k++; } } return n_color; } // ========================================================================== // Public Member functions // ========================================================================== /*! Compute user specified subset of a sparse Jacobian using forward mode. The C++ source code corresponding to this operation is \verbatim SparceJacobianForward(x, p, row, col, jac, work) \endverbatim \tparam Base is the base type for the recording that is stored in this ADFun object. \tparam VectorBase is a simple vector class with elements of type \a Base. \tparam VectorSet is a simple vector class with elements of type \c bool or \c std::set. \tparam VectorSize is a simple vector class with elements of type \c size_t. \param x [in] is a vector specifing the point at which to compute the Jacobian. \param p [in] is the sparsity pattern for the Jacobian that we are calculating. \param row [in] is the vector of row indices for the returned Jacobian values. \param col [in] is the vector of columns indices for the returned Jacobian values. It must have the same size as \c row. \param jac [out] is the vector of Jacobian values. It must have the same size as \c row. The return value jac[k] is the partial of the row[k] range component of the function with respect the the col[k] domain component of its argument. \param work [in,out] this structure contains information that depends on the function object, sparsity pattern, \c row vector, and \c col vector. If they are not the same between calls to \c SparseJacobianForward, \c work.clear() must be called to reinitialize them. \return Is the number of first order forward sweeps used to compute the requested Jacobian values. The total work, not counting the zero order forward sweep, or the time to combine computations, is proportional to this return value. */ template template size_t ADFun::SparseJacobianForward( const VectorBase& x , const VectorSet& p , const VectorSize& row , const VectorSize& col , VectorBase& jac , sparse_jacobian_work& work ) { size_t n = Domain(); size_t m = Range(); # ifndef NDEBUG size_t k, K = jac.size(); CPPAD_ASSERT_KNOWN( size_t(x.size()) == n , "SparseJacobianForward: size of x not equal domain dimension for f." ); CPPAD_ASSERT_KNOWN( size_t(row.size()) == K && size_t(col.size()) == K , "SparseJacobianForward: either r or c does not have " "the same size as jac." ); CPPAD_ASSERT_KNOWN( work.color.size() == 0 || work.color.size() == n, "SparseJacobianForward: invalid value in work." ); for(k = 0; k < K; k++) { CPPAD_ASSERT_KNOWN( row[k] < m, "SparseJacobianForward: invalid value in r." ); CPPAD_ASSERT_KNOWN( col[k] < n, "SparseJacobianForward: invalid value in c." ); } if( work.color.size() != 0 ) for(size_t j = 0; j < n; j++) CPPAD_ASSERT_KNOWN( work.color[j] <= n, "SparseJacobianForward: invalid value in work." ); # endif typedef typename VectorSet::value_type Set_type; typedef typename internal_sparsity::pattern_type Pattern_type; Pattern_type s_transpose; if( work.color.size() == 0 ) { bool transpose = true; sparsity_user2internal(s_transpose, p, m, n, transpose); } size_t n_sweep = SparseJacobianFor(x, s_transpose, row, col, jac, work); return n_sweep; } /*! Compute user specified subset of a sparse Jacobian using forward mode. The C++ source code corresponding to this operation is \verbatim SparceJacobianReverse(x, p, row, col, jac, work) \endverbatim \tparam Base is the base type for the recording that is stored in this ADFun object. \tparam VectorBase is a simple vector class with elements of type \a Base. \tparam VectorSet is a simple vector class with elements of type \c bool or \c std::set. \tparam VectorSize is a simple vector class with elements of type \c size_t. \param x [in] is a vector specifing the point at which to compute the Jacobian. \param p [in] is the sparsity pattern for the Jacobian that we are calculating. \param row [in] is the vector of row indices for the returned Jacobian values. \param col [in] is the vector of columns indices for the returned Jacobian values. It must have the same size as \c row. \param jac [out] is the vector of Jacobian values. It must have the same size as \c row. The return value jac[k] is the partial of the row[k] range component of the function with respect the the col[k] domain component of its argument. \param work [in,out] this structure contains information that depends on the function object, sparsity pattern, \c row vector, and \c col vector. If they are not the same between calls to \c SparseJacobianReverse, \c work.clear() must be called to reinitialize them. \return Is the number of first order reverse sweeps used to compute the reverse Jacobian values. The total work, not counting the zero order forward sweep, or the time to combine computations, is proportional to this return value. */ template template size_t ADFun::SparseJacobianReverse( const VectorBase& x , const VectorSet& p , const VectorSize& row , const VectorSize& col , VectorBase& jac , sparse_jacobian_work& work ) { size_t m = Range(); size_t n = Domain(); # ifndef NDEBUG size_t k, K = jac.size(); CPPAD_ASSERT_KNOWN( size_t(x.size()) == n , "SparseJacobianReverse: size of x not equal domain dimension for f." ); CPPAD_ASSERT_KNOWN( size_t(row.size()) == K && size_t(col.size()) == K , "SparseJacobianReverse: either r or c does not have " "the same size as jac." ); CPPAD_ASSERT_KNOWN( work.color.size() == 0 || work.color.size() == m, "SparseJacobianReverse: invalid value in work." ); for(k = 0; k < K; k++) { CPPAD_ASSERT_KNOWN( row[k] < m, "SparseJacobianReverse: invalid value in r." ); CPPAD_ASSERT_KNOWN( col[k] < n, "SparseJacobianReverse: invalid value in c." ); } if( work.color.size() != 0 ) for(size_t i = 0; i < m; i++) CPPAD_ASSERT_KNOWN( work.color[i] <= m, "SparseJacobianReverse: invalid value in work." ); # endif typedef typename VectorSet::value_type Set_type; typedef typename internal_sparsity::pattern_type Pattern_type; Pattern_type s; if( work.color.size() == 0 ) { bool transpose = false; sparsity_user2internal(s, p, m, n, transpose); } size_t n_sweep = SparseJacobianRev(x, s, row, col, jac, work); return n_sweep; } /*! Compute a sparse Jacobian. The C++ source code corresponding to this operation is \verbatim jac = SparseJacobian(x, p) \endverbatim \tparam Base is the base type for the recording that is stored in this ADFun object. \tparam VectorBase is a simple vector class with elements of type \a Base. \tparam VectorSet is a simple vector class with elements of type \c bool or \c std::set. \param x [in] is a vector specifing the point at which to compute the Jacobian. \param p [in] is the sparsity pattern for the Jacobian that we are calculating. \return Will be a vector if size \c m * n containing the Jacobian at the specified point (in row major order). */ template template VectorBase ADFun::SparseJacobian( const VectorBase& x, const VectorSet& p ) { size_t i, j, k; size_t m = Range(); size_t n = Domain(); VectorBase jac(m * n); CPPAD_ASSERT_KNOWN( size_t(x.size()) == n, "SparseJacobian: size of x not equal domain size for f." ); CheckSimpleVector(); typedef typename VectorSet::value_type Set_type; typedef typename internal_sparsity::pattern_type Pattern_type; // initialize the return value as zero Base zero(0); for(i = 0; i < m; i++) for(j = 0; j < n; j++) jac[i * n + j] = zero; sparse_jacobian_work work; CppAD::vector row; CppAD::vector col; if( n <= m ) { // need an internal copy of sparsity pattern Pattern_type s_transpose; bool transpose = true; sparsity_user2internal(s_transpose, p, m, n, transpose); k = 0; for(j = 0; j < n; j++) { s_transpose.begin(j); i = s_transpose.next_element(); while( i != s_transpose.end() ) { row.push_back(i); col.push_back(j); k++; i = s_transpose.next_element(); } } size_t K = k; VectorBase J(K); // now we have folded this into the following case SparseJacobianFor(x, s_transpose, row, col, J, work); // now set the non-zero return values for(k = 0; k < K; k++) jac[ row[k] * n + col[k] ] = J[k]; } else { // need an internal copy of sparsity pattern Pattern_type s; bool transpose = false; sparsity_user2internal(s, p, m, n, transpose); k = 0; for(i = 0; i < m; i++) { s.begin(i); j = s.next_element(); while( j != s.end() ) { row.push_back(i); col.push_back(j); k++; j = s.next_element(); } } size_t K = k; VectorBase J(K); // now we have folded this into the following case SparseJacobianRev(x, s, row, col, J, work); // now set the non-zero return values for(k = 0; k < K; k++) jac[ row[k] * n + col[k] ] = J[k]; } return jac; } /*! Compute a sparse Jacobian. The C++ source code corresponding to this operation is \verbatim jac = SparseJacobian(x) \endverbatim \tparam Base is the base type for the recording that is stored in this ADFun object. \tparam VectorBase is a simple vector class with elements of the \a Base. \param x [in] is a vector specifing the point at which to compute the Jacobian. \return Will be a vector of size \c m * n containing the Jacobian at the specified point (in row major order). */ template template VectorBase ADFun::SparseJacobian( const VectorBase& x ) { typedef CppAD::vectorBool VectorBool; size_t m = Range(); size_t n = Domain(); // sparsity pattern for Jacobian VectorBool p(m * n); if( n <= m ) { size_t j, k; // use forward mode VectorBool r(n * n); for(j = 0; j < n; j++) { for(k = 0; k < n; k++) r[j * n + k] = false; r[j * n + j] = true; } p = ForSparseJac(n, r); } else { size_t i, k; // use reverse mode VectorBool s(m * m); for(i = 0; i < m; i++) { for(k = 0; k < m; k++) s[i * m + k] = false; s[i * m + i] = true; } p = RevSparseJac(m, s); } return SparseJacobian(x, p); } } // END_CPPAD_NAMESPACE # undef CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION # endif TMB/inst/include/cppad/local/mul_eq.hpp0000644000176200001440000000544214536067013017462 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_MUL_EQ_INCLUDED # define CPPAD_MUL_EQ_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template AD& AD::operator *= (const AD &right) { // compute the Base part Base left; left = value_; value_ *= right.value_; // check if there is a recording in progress ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return *this; tape_id_t tape_id = tape->id_; // tape_id cannot match the default value for tape_id_; i.e., 0 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); bool var_left = tape_id_ == tape_id; bool var_right = right.tape_id_ == tape_id; if( var_left ) { if( var_right ) { // this = variable * variable CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 ); // put operand addresses in tape tape->Rec_.PutArg(taddr_, right.taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(MulvvOp); // make this a variable CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id ); } else if( IdenticalOne( right.value_ ) ) { // this = variable * 1 } else if( IdenticalZero( right.value_ ) ) { // this = variable * 0 make_parameter(); } else { // this = variable * parameter // = parameter * variable CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(right.value_); tape->Rec_.PutArg(p, taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(MulpvOp); // make this a variable CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id ); } } else if( var_right ) { if( IdenticalZero(left) ) { // this = 0 * right } else if( IdenticalOne(left) ) { // this = 1 * right make_variable(right.tape_id_, right.taddr_); } else { // this = parameter * variable CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 ); // put operand addresses in tape addr_t p = tape->Rec_.PutPar(left); tape->Rec_.PutArg(p, right.taddr_); // put operator in the tape taddr_ = tape->Rec_.PutOp(MulpvOp); // make this a variable tape_id_ = tape_id; } } return *this; } CPPAD_FOLD_ASSIGNMENT_OPERATOR(*=) } // END CppAD namespace # endif TMB/inst/include/cppad/local/equal_op_seq.hpp0000644000176200001440000000600714536067013020653 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_EQUAL_OP_SEQ_INCLUDED # define CPPAD_EQUAL_OP_SEQ_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------ $begin EqualOpSeq$$ $spell Op const bool $$ $index EqualOpSeq$$ $index operation, equal sequence$$ $index sequence, equal operation$$ $index equal, operation sequence$$ $section Check if Two Value are Identically Equal$$ $head Syntax$$ $icode%b% = EqualOpSeq(%x%, %y%)%$$ $head Purpose$$ Determine if two $icode x$$ and $icode y$$ are identically equal; i.e., not only is $icode%x% == %y%$$ true, but if they are $cref/variables/glossary/Variable/$$, they correspond have the same $cref/operation sequence/glossary/Operation/Sequence/$$. $head Motivation$$ Sometimes it is useful to cache information and only recalculate when a function's arguments change. In the case of AD variables, it may be important not only when the argument values are equal, but when they are related to the $cref/independent variables/glossary/Tape/Independent Variable/$$ by the same operation sequence. After the assignment $codei% %y% = %x% %$$ these two AD objects would not only have equal values, but would also correspond to the same operation sequence. $head x$$ The argument $icode x$$ has prototype $codei% const AD<%Base%> &%x% %$$ $head y$$ The argument $icode y$$ has prototype $codei% const AD<%Base%> &%y% %$$ $head b$$ The result $icode b$$ has prototype $codei% bool %b% %$$ The result is true if and only if one of the following cases holds: $list number$$ Both $icode x$$ and $icode y$$ are variables and correspond to the same operation sequence. $lnext Both $icode x$$ and $icode y$$ are parameters, $icode Base$$ is an AD type, and $codei%EqualOpSeq( Value(%x%) , Value(%y%) )%$$ is true. $lnext Both $icode x$$ and $icode y$$ are parameters, $icode Base$$ is not an AD type, and $icode%x% == %y%%$$ is true. $lend $head Example$$ $children% example/equal_op_seq.cpp %$$ The file $cref equal_op_seq.cpp$$ contains an example and test of $code EqualOpSeq$$. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------ */ namespace CppAD { template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool EqualOpSeq(const AD &x, const AD &y) { if( Parameter(x) ) { if( Parameter(y) ) return EqualOpSeq(x.value_, y.value_); else return false; } else if( Parameter(y) ) return false; return (x.taddr_ == y.taddr_); } } # endif TMB/inst/include/cppad/local/abort_recording.hpp0000644000176200001440000000337514536067013021346 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ABORT_RECORDING_INCLUDED # define CPPAD_ABORT_RECORDING_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin abort_recording$$ $spell $$ $section Abort Recording of an Operation Sequence$$ $index abort, operation sequence$$ $index operation, sequence abort$$ $index sequence, operation abort$$ $index recording, abort$$ $index tape, abort recording$$ $head Syntax$$ $codei%AD<%Base%>::abort_recording()%$$ $head Purpose$$ Sometimes it is necessary to abort the recording of an operation sequence that started with a call of the form $codei% Independent(%x%) %$$ If such a recording is currently in progress, $code abort_recording$$ will stop the recording and delete the corresponding information. Otherwise, $code abort_recording$$ has no effect. $children% example/abort_recording.cpp %$$ $head Example$$ The file $cref abort_recording.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ---------------------------------------------------------------------------- */ namespace CppAD { template void AD::abort_recording(void) { ADTape* tape = AD::tape_ptr(); if( tape != CPPAD_NULL ) AD::tape_manage(tape_manage_delete); } } # endif TMB/inst/include/cppad/local/ad.hpp0000644000176200001440000002124214536067013016560 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_AD_INCLUDED # define CPPAD_AD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // simple AD operations that must be defined for AD as well as base class # include # include // define the template classes that are used by the AD template class # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE typedef enum { tape_manage_new, tape_manage_delete, tape_manage_clear } tape_manage_job; template class AD { // enable use of AD in parallel mode template friend void parallel_ad(void); // template friend functions where template parameter is not bound template friend void Independent(VectorAD &x, size_t abort_op_index); // one argument functions friend bool Parameter (const AD &u); friend bool Parameter (const VecAD &u); friend bool Variable (const AD &u); friend bool Variable (const VecAD &u); friend int Integer (const AD &u); friend AD Var2Par (const AD &u); // power function friend AD pow (const AD &x, const AD &y); // order determining functions, see ordered.hpp friend bool GreaterThanZero (const AD &x); friend bool GreaterThanOrZero (const AD &x); friend bool LessThanZero (const AD &x); friend bool LessThanOrZero (const AD &x); friend bool abs_geq (const AD& x, const AD& y); // The identical property functions, see identical.hpp friend bool IdenticalPar (const AD &x); friend bool IdenticalZero (const AD &x); friend bool IdenticalOne (const AD &x); friend bool IdenticalEqualPar (const AD &x, const AD &y); // EqualOpSeq function friend bool EqualOpSeq (const AD &u, const AD &v); // NearEqual function friend bool NearEqual ( const AD &x, const AD &y, const Base &r, const Base &a); friend bool NearEqual ( const Base &x, const AD &y, const Base &r, const Base &a); friend bool NearEqual ( const AD &x, const Base &y, const Base &r, const Base &a); // CondExp function friend AD CondExpOp ( enum CompareOp cop , const AD &left , const AD &right , const AD &trueCase , const AD &falseCase ); // classes friend class ADTape; friend class ADFun; friend class atomic_base; friend class discrete; friend class VecAD; friend class VecAD_reference; // arithematic binary operators friend AD operator + (const AD &left, const AD &right); friend AD operator - (const AD &left, const AD &right); friend AD operator * (const AD &left, const AD &right); friend AD operator / (const AD &left, const AD &right); // comparison operators friend bool operator < (const AD &left, const AD &right); friend bool operator <= (const AD &left, const AD &right); friend bool operator > (const AD &left, const AD &right); friend bool operator >= (const AD &left, const AD &right); friend bool operator == (const AD &left, const AD &right); friend bool operator != (const AD &left, const AD &right); // input operator friend std::istream& operator >> (std::istream &is, AD &x); // output operations friend std::ostream& operator << (std::ostream &os, const AD &x); friend void PrintFor ( const AD& flag , const char* before , const AD& var , const char* after ); public: // type of value typedef Base value_type; // implicit default constructor inline AD(void); // use default implicit copy constructor and assignment operator // inline AD(const AD &x); // inline AD& operator=(const AD &x); // implicit construction and assingment from base type // Kasper: disabled because redundant (!) - see below // inline AD(const Base &b); inline AD& operator=(const Base &b); // implicit contructor and assignment from VecAD::reference inline AD(const VecAD_reference &x); inline AD& operator=(const VecAD_reference &x); # if CPPAD_IMPLICIT_CTOR_FROM_ANY_TYPE // implicit construction from some other type (depricated) template inline AD(const T &t); # else // explicit construction from some other type (depricated) template inline explicit AD(const T &t); # endif // Kasper: explicit CTOR does not allow e.g. 'AD > x = 0;' #define CTOR_FROM(TYPE) inline AD(const TYPE &t); CTOR_FROM(double) #undef CTOR_FROM // assignment from some other type template inline AD& operator=(const T &right); // base type corresponding to an AD object friend Base Value (const AD &x); // computed assignment operators inline AD& operator += (const AD &right); inline AD& operator -= (const AD &right); inline AD& operator *= (const AD &right); inline AD& operator /= (const AD &right); // unary operators inline AD operator +(void) const; inline AD operator -(void) const; // destructor ~AD(void) { } // interface so these functions need not be friends inline AD Abs(void) const; inline AD acos(void) const; inline AD asin(void) const; inline AD atan(void) const; inline AD cos(void) const; inline AD cosh(void) const; inline AD exp(void) const; inline AD fabs(void) const; inline AD log(void) const; inline AD sin(void) const; inline AD Sign(void) const; inline AD sinh(void) const; inline AD sqrt(void) const; inline AD tan(void) const; inline AD tanh(void) const; # if CPPAD_COMPILER_HAS_ERF inline AD erf(void) const; # endif // ---------------------------------------------------------- // static public member functions // abort current AD recording static void abort_recording(void); // set the maximum number of OpenMP threads (deprecated) static void omp_max_thread(size_t number); // These functions declared public so can be accessed by user through // a macro interface and are not intended for direct use. // The macro interface is documented in bool_fun.hpp. // Developer documentation for these fucntions is in bool_fun.hpp static inline bool UnaryBool( bool FunName(const Base &x), const AD &x ); static inline bool BinaryBool( bool FunName(const Base &x, const Base &y), const AD &x , const AD &y ); private: // value_ corresponding to this object Base value_; // Tape identifier corresponding to taddr tape_id_t tape_id_; // taddr_ in tape for this variable addr_t taddr_; // // Make this variable a parameter // void make_parameter(void) { CPPAD_ASSERT_UNKNOWN( Variable(*this) ); // currently a var tape_id_ = 0; } // // Make this parameter a new variable // void make_variable(size_t id, size_t taddr) { CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); // currently a par CPPAD_ASSERT_UNKNOWN( taddr > 0 ); // sure valid taddr taddr_ = taddr; tape_id_ = id; } // --------------------------------------------------------------- // tape linking functions // // not static inline ADTape* tape_this(void) const; // // static inline static tape_id_t** tape_id_handle(size_t thread); inline static tape_id_t* tape_id_ptr(size_t thread); inline static ADTape** tape_handle(size_t thread); static ADTape* tape_manage(tape_manage_job job); inline static ADTape* tape_ptr(void); inline static ADTape* tape_ptr(tape_id_t tape_id); }; // --------------------------------------------------------------------------- } // END_CPPAD_NAMESPACE // tape linking private functions # include // operations that expect the AD template class to be defined # endif TMB/inst/include/cppad/local/rev_one.hpp0000644000176200001440000001021314536067013017625 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_REV_ONE_INCLUDED # define CPPAD_REV_ONE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin RevOne$$ $spell dw Taylor const $$ $index derivative, first order driver$$ $index first, order derivative driver$$ $index driver, first order derivative$$ $index easy, derivative$$ $index driver, easy derivative$$ $index derivative, easy$$ $section First Order Derivative: Driver Routine$$ $head Syntax$$ $icode%dw% = %f%.RevOne(%x%, %i%)%$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. The syntax above sets $icode dw$$ to the derivative of $latex F_i$$ with respect to $latex x$$; i.e., $latex \[ dw = F_i^{(1)} (x) = \left[ \D{ F_i }{ x_0 } (x) , \cdots , \D{ F_i }{ x_{n-1} } (x) \right] \] $$ $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/RevOne Uses Forward/RevOne/RevOne Uses Forward/$$ below). $head x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ (see $cref/Vector/RevOne/Vector/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies that point at which to evaluate the derivative. $head i$$ The index $icode i$$ has prototype $codei% size_t %i% %$$ and is less than $latex m$$, the dimension of the $cref/range/seq_property/Range/$$ space for $icode f$$. It specifies the component of $latex F$$ that we are computing the derivative of. $head dw$$ The result $icode dw$$ has prototype $codei% %Vector% %dw% %$$ (see $cref/Vector/RevOne/Vector/$$ below) and its size is $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. The value of $icode dw$$ is the derivative of $latex F_i$$ evaluated at $icode x$$; i.e., for $latex j = 0 , \ldots , n - 1 $$ $latex \[. dw[ j ] = \D{ F_i }{ x_j } ( x ) \] $$ $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Base$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head RevOne Uses Forward$$ After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After a call to $code RevOne$$, the zero order Taylor coefficients correspond to $icode%f%.Forward(0, %x%)%$$ and the other coefficients are unspecified. $head Example$$ $children% example/rev_one.cpp %$$ The routine $cref/RevOne/rev_one.cpp/$$ is both an example and test. It returns $code true$$, if it succeeds and $code false$$ otherwise. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template template Vector ADFun::RevOne(const Vector &x, size_t i) { size_t i1; size_t n = Domain(); size_t m = Range(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( x.size() == n, "RevOne: Length of x not equal domain dimension for f" ); CPPAD_ASSERT_KNOWN( i < m, "RevOne: the index i is not less than range dimension for f" ); // point at which we are evaluating the derivative Forward(0, x); // component which are are taking the derivative of Vector w(m); for(i1 = 0; i1 < m; i1++) w[i1] = 0.; w[i] = Base(1); // dimension the return value Vector dw(n); // compute the return value dw = Reverse(1, w); return dw; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/testvector.hpp0000644000176200001440000000623114536067013020377 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_TESTVECTOR_INCLUDED # define CPPAD_TESTVECTOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin testvector$$ $spell CppAD cmake testvector cppad Eigen ifdef hpp std endif ublas $$ $index CPPAD_TESTVECTOR$$ $index vector, test$$ $index test, vector$$ $section Using The CppAD Test Vector Template Class$$ $head Syntax$$ $codei%CPPAD_TESTVECTOR(%Scalar%) %$$ $head Introduction$$ Many of the CppAD $cref/examples/example/$$ and tests use the $code CPPAD_TESTVECTOR$$ template class to pass information to CppAD. This is not a true template class because it's syntax uses $codei%(%Scalar%)%$$ instead of $codei%<%Scalar%>%$$. This enables us to use $codei% Eigen::Matrix<%Scalar%, Eigen::Dynamic, 1> %$$ as one of the possible cases for this 'template class'. $head CppAD::vector$$ If in the $cref/cmake command/cmake/CMake Command/$$ you specify $cref cppad_testvector$$ to be $code cppad$$, $code CPPAD_CPPADVECTOR$$ will be true. In this case, $code CPPAD_TESTVECTOR$$ is defined by the following source code: $codep */ # if CPPAD_CPPADVECTOR # define CPPAD_TESTVECTOR(Scalar) CppAD::vector< Scalar > # endif /* $$ In this case CppAD will use its own vector for many of its examples and tests. $head std::vector$$ If in the cmake command you specify $icode cppad_testvector$$ to be $code std$$, $code CPPAD_STDVECTOR$$ will be true. In this case, $code CPPAD_TESTVECTOR$$ is defined by the following source code: $codep */ # if CPPAD_STDVECTOR # include # define CPPAD_TESTVECTOR(Scalar) std::vector< Scalar > # endif /* $$ In this case CppAD will use standard vector for many of its examples and tests. $head boost::numeric::ublas::vector$$ If in the cmake command you specify $icode cppad_testvector$$ to be $code boost$$, $code CPPAD_BOOSTVECTOR$$ will be true. In this case, $code CPPAD_TESTVECTOR$$ is defined by the following source code: $codep */ # if CPPAD_BOOSTVECTOR # include # define CPPAD_TESTVECTOR(Scalar) boost::numeric::ublas::vector< Scalar > # endif /* $$ In this case CppAD will use this boost vector for many of its examples and tests. $head Eigen Vectors$$ If in the cmake command you specify $icode cppad_testvector$$ to be $code eigen$$, $code CPPAD_EIGENVECTOR$$ will be true. In this case, $code CPPAD_TESTVECTOR$$ is defined by the following source code: $codep */ # if CPPAD_EIGENVECTOR # include # define CPPAD_TESTVECTOR(Scalar) Eigen::Matrix< Scalar , Eigen::Dynamic, 1> # endif /* $$ In this case CppAD will use the Eigen vector for many of its examples and tests. $end ------------------------------------------------------------------------ */ # endif TMB/inst/include/cppad/local/bender_quad.hpp0000644000176200001440000002313714536067013020452 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BENDER_QUAD_INCLUDED # define CPPAD_BENDER_QUAD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin BenderQuad$$ $spell cppad.hpp BAvector gx gxx CppAD Fy dy Jacobian ADvector const dg ddg $$ $index Hessian, Bender$$ $index Jacobian, Bender$$ $index BenderQuad$$ $section Computing Jacobian and Hessian of Bender's Reduced Objective$$ $head Syntax$$ $codei% # include BenderQuad(%x%, %y%, %fun%, %g%, %gx%, %gxx%)%$$ $head See Also$$ $cref opt_val_hes$$ $head Problem$$ The type $cref/ADvector/BenderQuad/ADvector/$$ cannot be determined form the arguments above (currently the type $icode ADvector$$ must be $codei%CPPAD_TESTVECTOR(%Base%)%$$.) This will be corrected in the future by requiring $icode Fun$$ to define $icode%Fun%::vector_type%$$ which will specify the type $icode ADvector$$. $head Purpose$$ We are given the optimization problem $latex \[ \begin{array}{rcl} {\rm minimize} & F(x, y) & {\rm w.r.t.} \; (x, y) \in \B{R}^n \times \B{R}^m \end{array} \] $$ that is convex with respect to $latex y$$. In addition, we are given a set of equations $latex H(x, y)$$ such that $latex \[ H[ x , Y(x) ] = 0 \;\; \Rightarrow \;\; F_y [ x , Y(x) ] = 0 \] $$ (In fact, it is often the case that $latex H(x, y) = F_y (x, y)$$.) Furthermore, it is easy to calculate a Newton step for these equations; i.e., $latex \[ dy = - [ \partial_y H(x, y)]^{-1} H(x, y) \] $$ The purpose of this routine is to compute the value, Jacobian, and Hessian of the reduced objective function $latex \[ G(x) = F[ x , Y(x) ] \] $$ Note that if only the value and Jacobian are needed, they can be computed more quickly using the relations $latex \[ G^{(1)} (x) = \partial_x F [x, Y(x) ] \] $$ $head x$$ The $code BenderQuad$$ argument $icode x$$ has prototype $codei% const %BAvector% &%x% %$$ (see $cref/BAvector/BenderQuad/BAvector/$$ below) and its size must be equal to $icode n$$. It specifies the point at which we evaluating the reduced objective function and its derivatives. $head y$$ The $code BenderQuad$$ argument $icode y$$ has prototype $codei% const %BAvector% &%y% %$$ and its size must be equal to $icode m$$. It must be equal to $latex Y(x)$$; i.e., it must solve the problem in $latex y$$ for this given value of $latex x$$ $latex \[ \begin{array}{rcl} {\rm minimize} & F(x, y) & {\rm w.r.t.} \; y \in \B{R}^m \end{array} \] $$ $head fun$$ The $code BenderQuad$$ object $icode fun$$ must support the member functions listed below. The $codei%AD<%Base%>%$$ arguments will be variables for a tape created by a call to $cref Independent$$ from $code BenderQuad$$ (hence they can not be combined with variables corresponding to a different tape). $subhead fun.f$$ The $code BenderQuad$$ argument $icode fun$$ supports the syntax $codei% %f% = %fun%.f(%x%, %y%) %$$ The $icode%fun%.f%$$ argument $icode x$$ has prototype $codei% const %ADvector% &%x% %$$ (see $cref/ADvector/BenderQuad/ADvector/$$ below) and its size must be equal to $icode n$$. The $icode%fun%.f%$$ argument $icode y$$ has prototype $codei% const %ADvector% &%y% %$$ and its size must be equal to $icode m$$. The $icode%fun%.f%$$ result $icode f$$ has prototype $codei% %ADvector% %f% %$$ and its size must be equal to one. The value of $icode f$$ is $latex \[ f = F(x, y) \] $$. $subhead fun.h$$ The $code BenderQuad$$ argument $icode fun$$ supports the syntax $codei% %h% = %fun%.h(%x%, %y%) %$$ The $icode%fun%.h%$$ argument $icode x$$ has prototype $codei% const %ADvector% &%x% %$$ and its size must be equal to $icode n$$. The $icode%fun%.h%$$ argument $icode y$$ has prototype $codei% const %BAvector% &%y% %$$ and its size must be equal to $icode m$$. The $icode%fun%.h%$$ result $icode h$$ has prototype $codei% %ADvector% %h% %$$ and its size must be equal to $icode m$$. The value of $icode h$$ is $latex \[ h = H(x, y) \] $$. $subhead fun.dy$$ The $code BenderQuad$$ argument $icode fun$$ supports the syntax $codei% %dy% = %fun%.dy(%x%, %y%, %h%) %x% %$$ The $icode%fun%.dy%$$ argument $icode x$$ has prototype $codei% const %BAvector% &%x% %$$ and its size must be equal to $icode n$$. Its value will be exactly equal to the $code BenderQuad$$ argument $icode x$$ and values depending on it can be stored as private objects in $icode f$$ and need not be recalculated. $codei% %y% %$$ The $icode%fun%.dy%$$ argument $icode y$$ has prototype $codei% const %BAvector% &%y% %$$ and its size must be equal to $icode m$$. Its value will be exactly equal to the $code BenderQuad$$ argument $icode y$$ and values depending on it can be stored as private objects in $icode f$$ and need not be recalculated. $codei% %h% %$$ The $icode%fun%.dy%$$ argument $icode h$$ has prototype $codei% const %ADvector% &%h% %$$ and its size must be equal to $icode m$$. $codei% %dy% %$$ The $icode%fun%.dy%$$ result $icode dy$$ has prototype $codei% %ADvector% %dy% %$$ and its size must be equal to $icode m$$. The return value $icode dy$$ is given by $latex \[ dy = - [ \partial_y H (x , y) ]^{-1} h \] $$ Note that if $icode h$$ is equal to $latex H(x, y)$$, $latex dy$$ is the Newton step for finding a zero of $latex H(x, y)$$ with respect to $latex y$$; i.e., $latex y + dy$$ is an approximate solution for the equation $latex H (x, y + dy) = 0$$. $head g$$ The argument $icode g$$ has prototype $codei% %BAvector% &%g% %$$ and has size one. The input value of its element does not matter. On output, it contains the value of $latex G (x)$$; i.e., $latex \[ g[0] = G (x) \] $$ $head gx$$ The argument $icode gx$$ has prototype $codei% %BAvector% &%gx% %$$ and has size $latex n $$. The input values of its elements do not matter. On output, it contains the Jacobian of $latex G (x)$$; i.e., for $latex j = 0 , \ldots , n-1$$, $latex \[ gx[ j ] = G^{(1)} (x)_j \] $$ $head gxx$$ The argument $icode gx$$ has prototype $codei% %BAvector% &%gxx% %$$ and has size $latex n \times n$$. The input values of its elements do not matter. On output, it contains the Hessian of $latex G (x)$$; i.e., for $latex i = 0 , \ldots , n-1$$, and $latex j = 0 , \ldots , n-1$$, $latex \[ gxx[ i * n + j ] = G^{(2)} (x)_{i,j} \] $$ $head BAvector$$ The type $icode BAvector$$ must be a $cref SimpleVector$$ class. We use $icode Base$$ to refer to the type of the elements of $icode BAvector$$; i.e., $codei% %BAvector%::value_type %$$ $head ADvector$$ The type $icode ADvector$$ must be a $cref SimpleVector$$ class with elements of type $codei%AD<%Base%>%$$; i.e., $codei% %ADvector%::value_type %$$ must be the same type as $codei% AD< %BAvector%::value_type > %$$. $head Example$$ $children% example/bender_quad.cpp %$$ The file $cref bender_quad.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ namespace CppAD { // BEGIN CppAD namespace template void BenderQuad( const BAvector &x , const BAvector &y , Fun fun , BAvector &g , BAvector &gx , BAvector &gxx ) { // determine the base type typedef typename BAvector::value_type Base; // check that BAvector is a SimpleVector class CheckSimpleVector(); // declare the ADvector type typedef CPPAD_TESTVECTOR(AD) ADvector; // size of the x and y spaces size_t n = size_t(x.size()); size_t m = size_t(y.size()); // check the size of gx and gxx CPPAD_ASSERT_KNOWN( g.size() == 1, "BenderQuad: size of the vector g is not equal to 1" ); CPPAD_ASSERT_KNOWN( size_t(gx.size()) == n, "BenderQuad: size of the vector gx is not equal to n" ); CPPAD_ASSERT_KNOWN( size_t(gxx.size()) == n * n, "BenderQuad: size of the vector gxx is not equal to n * n" ); // some temporary indices size_t i, j; // variable versions x ADvector vx(n); for(j = 0; j < n; j++) vx[j] = x[j]; // declare the independent variables Independent(vx); // evaluate h = H(x, y) ADvector h(m); h = fun.h(vx, y); // evaluate dy (x) = Newton step as a function of x through h only ADvector dy(m); dy = fun.dy(x, y, h); // variable version of y ADvector vy(m); for(j = 0; j < m; j++) vy[j] = y[j] + dy[j]; // evaluate G~ (x) = F [ x , y + dy(x) ] ADvector gtilde(1); gtilde = fun.f(vx, vy); // AD function object that corresponds to G~ (x) // We will make heavy use of this tape, so optimize it ADFun Gtilde; Gtilde.Dependent(vx, gtilde); Gtilde.optimize(); // value of G(x) g = Gtilde.Forward(0, x); // initial forward direction vector as zero BAvector dx(n); for(j = 0; j < n; j++) dx[j] = Base(0); // weight, first and second order derivative values BAvector dg(1), w(1), ddw(2 * n); w[0] = 1.; // Jacobian and Hessian of G(x) is equal Jacobian and Hessian of Gtilde for(j = 0; j < n; j++) { // compute partials in x[j] direction dx[j] = Base(1); dg = Gtilde.Forward(1, dx); gx[j] = dg[0]; // restore the dx vector to zero dx[j] = Base(0); // compute second partials w.r.t x[j] and x[l] for l = 1, n ddw = Gtilde.Reverse(2, w); for(i = 0; i < n; i++) gxx[ i * n + j ] = ddw[ i * 2 + 1 ]; } return; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/near_equal_ext.hpp0000644000176200001440000001171514536067013021174 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_NEAR_EQUAL_EXT_INCLUDED # define CPPAD_NEAR_EQUAL_EXT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin NearEqualExt$$ $spell Rcout endl Microsoft std Cpp namespace const bool $$ $section Compare AD and Base Objects for Nearly Equal$$ $index NearEqual, AD with Base$$ $head Syntax$$ $icode%b% = NearEqual(%x%, %y%, %r%, %a%)%$$ $head Purpose$$ The routine $cref NearEqual$$ determines if two objects of the same type are nearly. This routine is extended to the case where one object can have type $icode Type$$ while the other can have type $codei%AD<%Type%>%$$ or $codei%AD< std::complex<%Type%> >%$$. $head x$$ The arguments $icode x$$ has one of the following possible prototypes: $codei% const %Type% &%x% const AD<%Type%> &%x% const AD< std::complex<%Type%> > &%x% %$$ $head y$$ The arguments $icode y$$ has one of the following possible prototypes: $codei% const %Type% &%y% const AD<%Type%> &%y% const AD< std::complex<%Type%> > &%x% %$$ $head r$$ The relative error criteria $icode r$$ has prototype $codei% const %Type% &%r% %$$ It must be greater than or equal to zero. The relative error condition is defined as: $latex \[ \frac{ | x - y | } { |x| + |y| } \leq r \] $$ $head a$$ The absolute error criteria $icode a$$ has prototype $codei% const %Type% &%a% %$$ It must be greater than or equal to zero. The absolute error condition is defined as: $latex \[ | x - y | \leq a \] $$ $head b$$ The return value $icode b$$ has prototype $codei% bool %b% %$$ If either $icode x$$ or $icode y$$ is infinite or not a number, the return value is false. Otherwise, if either the relative or absolute error condition (defined above) is satisfied, the return value is true. Otherwise, the return value is false. $head Type$$ The type $icode Type$$ must be a $cref NumericType$$. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. If $icode a$$ and $icode b$$ have type $icode Type$$, the following operation must be defined $table $bold Operation$$ $cnext $bold Description$$ $rnext $icode%a% <= %b%$$ $cnext less that or equal operator (returns a $code bool$$ object) $tend $head Operation Sequence$$ The result of this operation is not an $cref/AD of Base/glossary/AD of Base/$$ object. Thus it will not be recorded as part of an AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Example$$ $children% example/near_equal_ext.cpp %$$ The file $cref near_equal_ext.cpp$$ contains an example and test of this extension of $cref NearEqual$$. It return true if it succeeds and false otherwise. $end */ // BEGIN CppAD namespace namespace CppAD { // ------------------------------------------------------------------------ // fold into base type and then use template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool NearEqual( const AD &x, const AD &y, const Base &r, const Base &a) { return NearEqual(x.value_, y.value_, r, a); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool NearEqual( const Base &x, const AD &y, const Base &r, const Base &a) { return NearEqual(x, y.value_, r, a); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool NearEqual( const AD &x, const Base &y, const Base &r, const Base &a) { return NearEqual(x.value_, y, r, a); } // fold into AD type and then use cases above template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool NearEqual( const VecAD_reference &x, const VecAD_reference &y, const Base &r, const Base &a) { return NearEqual(x.ADBase(), y.ADBase(), r, a); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool NearEqual(const VecAD_reference &x, const AD &y, const Base &r, const Base &a) { return NearEqual(x.ADBase(), y, r, a); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool NearEqual(const VecAD_reference &x, const Base &y, const Base &r, const Base &a) { return NearEqual(x.ADBase(), y, r, a); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool NearEqual(const AD &x, const VecAD_reference &y, const Base &r, const Base &a) { return NearEqual(x, y.ADBase(), r, a); } template CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool NearEqual(const Base &x, const VecAD_reference &y, const Base &r, const Base &a) { return NearEqual(x, y.ADBase(), r, a); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/forward.hpp0000644000176200001440000002615214536067013017645 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FORWARD_INCLUDED # define CPPAD_FORWARD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // documened after Forward but included here so easy to see # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file forward.hpp User interface to forward mode computations. */ /*! Multiple orders, one direction, forward mode Taylor coefficieints. \tparam Base The type used during the forward mode computations; i.e., the corresponding recording of operations used the type AD. \tparam VectorBase is a Simple Vector class with eleements of type Base. \param q is the hightest order for this forward mode computation; i.e., after this calculation there will be q+1 Taylor coefficients per variable. \param xq contains Taylor coefficients for the independent variables. The size of xq must either be n or (q+1)*n, We define p = q + 1 - xq.size()/n. For j = 0 , ... , n-1, k = p, ... , q, are xq[ (q+1-p)*j + k - p ] is the k-th order coefficient for the j-th independent variable. \param s Is the stream where output corresponding to PriOp operations will written. \return contains Taylor coefficients for the dependent variables. The size of the return value y is m*(q+1-p). For i = 0, ... , m-1, k = p, ..., q, y[(q+1-p)*i + (k-p)] is the k-th order coefficient for the i-th dependent variable. \par taylor_ The Taylor coefficients up to order p-1 are inputs and the coefficents from order p through q are outputs. Let N = num_var_tape_, and C = cap_order_taylor_. Note that for i = 1 , ..., N-1, k = 0 , ..., q, taylor_[ C*i + k ] is the k-th order cofficent, for the i-th varaible on the tape. (The first independent variable has index one on the tape and there is no variable with index zero.) */ template template VectorBase ADFun::Forward( size_t q , const VectorBase& xq , std::ostream& s ) { // temporary indices size_t i, j, k; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables size_t m = dep_taddr_.size(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( size_t(xq.size()) == n || size_t(xq.size()) == n*(q+1), "Forward(q, xq): xq.size() is not equal n or n*(q+1)" ); // lowest order we are computing size_t p = q + 1 - size_t(xq.size()) / n; CPPAD_ASSERT_UNKNOWN( p == 0 || p == q ); CPPAD_ASSERT_KNOWN( q <= num_order_taylor_ || p == 0, "Forward(q, xq): Number of Taylor coefficient orders stored in this" " ADFun\nis less than q and xq.size() != n*(q+1)." ); CPPAD_ASSERT_KNOWN( p <= 1 || num_direction_taylor_ == 1, "Forward(q, xq): computing order q >= 2" " and number of directions is not one." "\nMust use Forward(q, r, xq) for this case" ); // does taylor_ need more orders or fewer directions if( (cap_order_taylor_ <= q) | (num_direction_taylor_ != 1) ) { if( p == 0 ) { // no need to copy old values during capacity_order num_order_taylor_ = 0; } else num_order_taylor_ = q; size_t c = std::max(q + 1, cap_order_taylor_); size_t r = 1; capacity_order(c, r); } CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q ); CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 1 ); // short hand notation for order capacity size_t C = cap_order_taylor_; // set Taylor coefficients for independent variables for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ ); // ind_taddr_[j] is operator taddr for j-th independent variable CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); if( p == q ) taylor_[ C * ind_taddr_[j] + q] = xq[j]; else { for(k = 0; k <= q; k++) taylor_[ C * ind_taddr_[j] + k] = xq[ (q+1)*j + k]; } } // evaluate the derivatives CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() ); CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() ); if( q == 0 ) { forward0sweep(s, true, n, num_var_tape_, &play_, C, taylor_.data(), cskip_op_.data(), load_op_, compare_change_count_, compare_change_number_, compare_change_op_index_ ); } else { forward1sweep(s, true, p, q, n, num_var_tape_, &play_, C, taylor_.data(), cskip_op_.data(), load_op_, compare_change_count_, compare_change_number_, compare_change_op_index_ ); } // return Taylor coefficients for dependent variables VectorBase yq; if( p == q ) { yq.resize(m); for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); yq[i] = taylor_[ C * dep_taddr_[i] + q]; } } else { yq.resize(m * (q+1) ); for(i = 0; i < m; i++) { for(k = 0; k <= q; k++) yq[ (q+1) * i + k] = taylor_[ C * dep_taddr_[i] + k ]; } } # ifndef NDEBUG if( check_for_nan_ ) { bool ok = true; if( p == 0 ) { for(i = 0; i < m; i++) { // Visual Studio 2012, CppAD required in front of isnan ? ok &= ! CppAD::isnan( yq[ (q+1) * i + 0 ] ); } } CPPAD_ASSERT_KNOWN(ok, "yq = f.Forward(q, xq): has a zero order Taylor coefficient " "with the value nan." ); if( 0 < q ) { for(i = 0; i < m; i++) { for(k = p; k <= q; k++) { // Studio 2012, CppAD required in front of isnan ? ok &= ! CppAD::isnan( yq[ (q+1-p)*i + k-p ] ); } } } CPPAD_ASSERT_KNOWN(ok, "yq = f.Forward(q, xq): has a non-zero order Taylor coefficient\n" "with the value nan (but zero order coefficients are not nan)." ); } # endif // now we have q + 1 taylor_ coefficient orders per variable num_order_taylor_ = q + 1; return yq; } /*! One order, multiple directions, forward mode Taylor coefficieints. \tparam Base The type used during the forward mode computations; i.e., the corresponding recording of operations used the type AD. \tparam VectorBase is a Simple Vector class with eleements of type Base. \param q is the order for this forward mode computation, q > 0. There must be at least q Taylor coefficients per variable before this call. After this call there will be q+1 Taylor coefficients per variable. \param r is the number of directions for this calculation. If q != 1, \c r must be the same as in the previous call to Forward where \c q was equal to one. \param xq contains Taylor coefficients for the independent variables. The size of xq must either be r*n, For j = 0 , ... , n-1, ell = 0, ... , r-1, xq[ ( r*j + ell ] is the q-th order coefficient for the j-th independent variable and the ell-th direction. \return contains Taylor coefficients for the dependent variables. The size of the return value \c y is r*m. For i = 0, ... , m-1, ell = 0, ... , r-1, y[ r*i + ell ] is the q-th order coefficient for the i-th dependent variable and the ell-th direction. \par taylor_ The Taylor coefficients up to order q-1 are inputs and the coefficents of order \c q are outputs. Let N = num_var_tape_, and C = cap_order_taylor_. Note that for i = 1 , ..., N-1, taylor_[ (C-1)*r*i + i + 0 ] is the zero order cofficent, for the i-th varaible, and all directions. For i = 1 , ..., N-1, k = 1 , ..., q, ell = 0 , ..., r-1, taylor_[ (C-1)*r*i + i + (k-1)*r + ell + 1 ] is the k-th order cofficent, for the i-th varaible, and ell-th direction. (The first independent variable has index one on the tape and there is no variable with index zero.) */ template template VectorBase ADFun::Forward( size_t q , size_t r , const VectorBase& xq ) { // temporary indices size_t i, j, ell; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables size_t m = dep_taddr_.size(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_KNOWN( q > 0, "Forward(q, r, xq): q == 0" ); CPPAD_ASSERT_KNOWN( size_t(xq.size()) == r * n, "Forward(q, r, xq): xq.size() is not equal r * n" ); CPPAD_ASSERT_KNOWN( q <= num_order_taylor_ , "Forward(q, r, xq): Number of Taylor coefficient orders stored in" " this ADFun is less than q" ); CPPAD_ASSERT_KNOWN( q == 1 || num_direction_taylor_ == r , "Forward(q, r, xq): q > 1 and number of Taylor directions r" " is not same as previous Forward(1, r, xq)" ); // does taylor_ need more orders or new number of directions if( cap_order_taylor_ <= q || num_direction_taylor_ != r ) { if( num_direction_taylor_ != r ) num_order_taylor_ = 1; size_t c = std::max(q + 1, cap_order_taylor_); capacity_order(c, r); } CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q ); CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == r ) // short hand notation for order capacity size_t c = cap_order_taylor_; // set Taylor coefficients for independent variables for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ ); // ind_taddr_[j] is operator taddr for j-th independent variable CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); for(ell = 0; ell < r; ell++) { size_t index = ((c-1)*r + 1)*ind_taddr_[j] + (q-1)*r + ell + 1; taylor_[ index ] = xq[ r * j + ell ]; } } // evaluate the derivatives CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() ); CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() ); forward2sweep( q, r, n, num_var_tape_, &play_, c, taylor_.data(), cskip_op_.data(), load_op_ ); // return Taylor coefficients for dependent variables VectorBase yq; yq.resize(r * m); for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); for(ell = 0; ell < r; ell++) { size_t index = ((c-1)*r + 1)*dep_taddr_[i] + (q-1)*r + ell + 1; yq[ r * i + ell ] = taylor_[ index ]; } } # ifndef NDEBUG if( check_for_nan_ ) { bool ok = true; for(i = 0; i < m; i++) { for(ell = 0; ell < r; ell++) { // Studio 2012, CppAD required in front of isnan ? ok &= ! CppAD::isnan( yq[ r * i + ell ] ); } } CPPAD_ASSERT_KNOWN(ok, "yq = f.Forward(q, r, xq): has a non-zero order Taylor coefficient\n" "with the value nan (but zero order coefficients are not nan)." ); } # endif // now we have q + 1 taylor_ coefficient orders per variable num_order_taylor_ = q + 1; return yq; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/add_op.hpp0000644000176200001440000002162114536067013017423 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ADD_OP_INCLUDED # define CPPAD_ADD_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file add_op.hpp Forward and reverse mode calculations for z = x + y. */ // --------------------------- Addvv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = AddvvOp. The C++ source code corresponding to this operation is \verbatim z = x + y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op */ template inline void forward_addvv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; for(size_t j = p; j <= q; j++) z[j] = x[j] + y[j]; } /*! Multiple directions forward mode Taylor coefficients for op = AddvvOp. The C++ source code corresponding to this operation is \verbatim z = x + y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op_dir */ template inline void forward_addvv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( 0 < q ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + arg[0] * num_taylor_per_var; Base* y = taylor + arg[1] * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; size_t m = (q-1)*r + 1 ; for(size_t ell = 0; ell < r; ell++) z[m+ell] = x[m+ell] + y[m+ell]; } /*! Compute zero order forward mode Taylor coefficients for result of op = AddvvOp. The C++ source code corresponding to this operation is \verbatim z = x + y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails forward_binary_op_0 */ template inline void forward_addvv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 ); // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x[0] + y[0]; } /*! Compute reverse mode partial derivatives for result of op = AddvvOp. The C++ source code corresponding to this operation is \verbatim z = x + y \endverbatim In the documentation below, this operations is for the case where both x and y are variables and the argument \a parameter is not used. \copydetails reverse_binary_op */ template inline void reverse_addvv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Partial derivatives corresponding to arguments and result Base* px = partial + arg[0] * nc_partial; Base* py = partial + arg[1] * nc_partial; Base* pz = partial + i_z * nc_partial; // number of indices to access size_t i = d + 1; while(i) { --i; px[i] += pz[i]; py[i] += pz[i]; } } // --------------------------- Addpv ----------------------------------------- /*! Compute forward mode Taylor coefficients for result of op = AddpvOp. The C++ source code corresponding to this operation is \verbatim z = x + y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op */ template inline void forward_addpv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; if( p == 0 ) { // Paraemter value Base x = parameter[ arg[0] ]; z[0] = x + y[0]; p++; } for(size_t j = p; j <= q; j++) z[j] = y[j]; } /*! Multiple directions forward mode Taylor coefficients for op = AddpvOp. The C++ source code corresponding to this operation is \verbatim z = x + y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op_dir */ template inline void forward_addpv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; size_t m = (q-1) * r + 1; Base* y = taylor + arg[1] * num_taylor_per_var + m; Base* z = taylor + i_z * num_taylor_per_var + m; for(size_t ell = 0; ell < r; ell++) z[ell] = y[ell]; } /*! Compute zero order forward mode Taylor coefficient for result of op = AddpvOp. The C++ source code corresponding to this operation is \verbatim z = x + y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails forward_binary_op_0 */ template inline void forward_addpv_op_0( size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); // Paraemter value Base x = parameter[ arg[0] ]; // Taylor coefficients corresponding to arguments and result Base* y = taylor + arg[1] * cap_order; Base* z = taylor + i_z * cap_order; z[0] = x + y[0]; } /*! Compute reverse mode partial derivative for result of op = AddpvOp. The C++ source code corresponding to this operation is \verbatim z = x + y \endverbatim In the documentation below, this operations is for the case where x is a parameter and y is a variable. \copydetails reverse_binary_op */ template inline void reverse_addpv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Partial derivatives corresponding to arguments and result Base* py = partial + arg[1] * nc_partial; Base* pz = partial + i_z * nc_partial; // number of indices to access size_t i = d + 1; while(i) { --i; py[i] += pz[i]; } } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/dependent.hpp0000644000176200001440000002232114536067013020141 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DEPENDENT_INCLUDED # define CPPAD_DEPENDENT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Dependent$$ $spell alloc num taylor_ ADvector const $$ $spell $$ $section Stop Recording and Store Operation Sequence$$ $index ADFun, operation sequence$$ $index operation, sequence store$$ $index sequence, operation store$$ $index recording, stop$$ $index tape, stop recording$$ $index Dependent$$ $head Syntax$$ $icode%f%.Dependent(%x%, %y%)%$$ $head Purpose$$ Stop recording and the AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$ that started with the call $codei% Independent(%x%) %$$ and store the operation sequence in $icode f$$. The operation sequence defines an $cref/AD function/glossary/AD Function/$$ $latex \[ F : B^n \rightarrow B^m \] $$ where $latex B$$ is the space corresponding to objects of type $icode Base$$. The value $latex n$$ is the dimension of the $cref/domain/seq_property/Domain/$$ space for the operation sequence. The value $latex m$$ is the dimension of the $cref/range/seq_property/Range/$$ space for the operation sequence (which is determined by the size of $icode y$$). $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ The AD of $icode Base$$ operation sequence is stored in $icode f$$; i.e., it becomes the operation sequence corresponding to $icode f$$. If a previous operation sequence was stored in $icode f$$, it is deleted. $head x$$ The argument $icode x$$ must be the vector argument in a previous call to $cref Independent$$. Neither its size, or any of its values, are allowed to change between calling $codei% Independent(%x%) %$$ and $codei% %f%.Dependent(%x%, %y%) %$$. $head y$$ The vector $icode y$$ has prototype $codei% const %ADvector% &%y% %$$ (see $cref/ADvector/FunConstruct/$$ below). The length of $icode y$$ must be greater than zero and is the dimension of the range space for $icode f$$. $head ADvector$$ The type $icode ADvector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $codei%AD<%Base%>%$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Taping$$ The tape, that was created when $codei%Independent(%x%)%$$ was called, will stop recording. The AD operation sequence will be transferred from the tape to the object $icode f$$ and the tape will then be deleted. $head Forward$$ No $cref Forward$$ calculation is preformed during this operation. Thus, directly after this operation, $codei% %f%.size_order() %$$ is zero (see $cref size_order$$). $head Parallel Mode$$ $index parallel, Dependent$$ $index Dependent, parallel$$ The call to $code Independent$$, and the corresponding call to $codei% ADFun<%Base%> %f%( %x%, %y%) %$$ or $codei% %f%.Dependent( %x%, %y%) %$$ or $cref abort_recording$$, must be preformed by the same thread; i.e., $cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same. $head Example$$ The file $cref fun_check.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ---------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { /*! \file dependent.hpp Different versions of Dependent function. */ /*! Determine the \c tape corresponding to this exeuction thread and then use Dependent(tape, y) to store this tapes recording in a function. \param y [in] The dependent variable vector for the corresponding function. */ template template void ADFun::Dependent(const ADvector &y) { ADTape* tape = AD::tape_ptr(); CPPAD_ASSERT_KNOWN( tape != CPPAD_NULL, "Can't store current operation sequence in this ADFun object" "\nbecause there is no active tape (for this thread)." ); // code above just determines the tape and checks for errors Dependent(tape, y); } /*! Determine the \c tape corresponding to this exeuction thread and then use Dependent(tape, y) to store this tapes recording in a function. \param x [in] The independent variable vector for this tape. This informaiton is also stored in the tape so a check is done to make sure it is correct (if NDEBUG is not defined). \param y [in] The dependent variable vector for the corresponding function. */ template template void ADFun::Dependent(const ADvector &x, const ADvector &y) { CPPAD_ASSERT_KNOWN( x.size() > 0, "Dependent: independent variable vector has size zero." ); CPPAD_ASSERT_KNOWN( Variable(x[0]), "Dependent: independent variable vector has been changed." ); ADTape *tape = AD::tape_ptr(x[0].tape_id_); CPPAD_ASSERT_KNOWN( tape->size_independent_ == size_t( x.size() ), "Dependent: independent variable vector has been changed." ); # ifndef NDEBUG size_t i, j; for(j = 0; j < size_t(x.size()); j++) { CPPAD_ASSERT_KNOWN( size_t(x[j].taddr_) == (j+1), "ADFun: independent variable vector has been changed." ); CPPAD_ASSERT_KNOWN( x[j].tape_id_ == x[0].tape_id_, "ADFun: independent variable vector has been changed." ); } for(i = 0; i < size_t(y.size()); i++) { CPPAD_ASSERT_KNOWN( CppAD::Parameter( y[i] ) | (y[i].tape_id_ == x[0].tape_id_) , "ADFun: dependent vector contains a variable for" "\na different tape (thread) than the independent variables." ); } # endif // code above just determines the tape and checks for errors Dependent(tape, y); } /*! Replace the floationg point operations sequence for this function object. \param tape is a tape that contains the new floating point operation sequence for this function. After this operation, all memory allocated for this tape is deleted. \param y The dependent variable vector for the function being stored in this object. \par All of the private member data in ad_fun.hpp is set to correspond to the new tape except for check_for_nan_. */ template template void ADFun::Dependent(ADTape *tape, const ADvector &y) { size_t m = y.size(); size_t n = tape->size_independent_; size_t i, j; size_t y_taddr; // check ADvector is Simple Vector class with AD elements CheckSimpleVector< AD, ADvector>(); CPPAD_ASSERT_KNOWN( y.size() > 0, "ADFun operation sequence dependent variable size is zero size" ); // --------------------------------------------------------------------- // Begin setting ad_fun.hpp private member data // --------------------------------------------------------------------- // dep_parameter_, dep_taddr_ CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 ); dep_parameter_.resize(m); dep_taddr_.resize(m); for(i = 0; i < m; i++) { dep_parameter_[i] = CppAD::Parameter(y[i]); if( dep_parameter_[i] ) { // make a tape copy of dependent variables that are parameters, y_taddr = tape->RecordParOp( y[i].value_ ); } else y_taddr = y[i].taddr_; CPPAD_ASSERT_UNKNOWN( y_taddr > 0 ); dep_taddr_[i] = y_taddr; } // put an EndOp at the end of the tape tape->Rec_.PutOp(EndOp); // some size_t values in ad_fun.hpp has_been_optimized_ = false; compare_change_count_ = 1; compare_change_number_ = 0; compare_change_op_index_ = 0; num_order_taylor_ = 0; num_direction_taylor_ = 0; cap_order_taylor_ = 0; // num_var_tape_ // Now that all the variables are in the tape, we can set this value. num_var_tape_ = tape->Rec_.num_var_rec(); // taylor_ taylor_.erase(); // cskip_op_ cskip_op_.erase(); cskip_op_.extend( tape->Rec_.num_op_rec() ); // load_op_ load_op_.erase(); load_op_.extend( tape->Rec_.num_load_op_rec() ); // play_ // Now that each dependent variable has a place in the tape, // and there is a EndOp at the end of the tape, we can transfer the // recording to the player and and erase the tape. play_.get(tape->Rec_); // ind_taddr_ // Note that play_ has been set, we can use it to check operators ind_taddr_.resize(n); CPPAD_ASSERT_UNKNOWN( n < num_var_tape_); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == InvOp ); ind_taddr_[j] = j+1; } // for_jac_sparse_pack_, for_jac_sparse_set_ for_jac_sparse_pack_.resize(0, 0); for_jac_sparse_set_.resize(0,0); // --------------------------------------------------------------------- // End set ad_fun.hpp private member data // --------------------------------------------------------------------- // now we can delete the tape AD::tape_manage(tape_manage_delete); // total number of varables in this recording CPPAD_ASSERT_UNKNOWN( num_var_tape_ == play_.num_var_rec() ); // used to determine if there is an operation sequence in *this CPPAD_ASSERT_UNKNOWN( num_var_tape_ > 0 ); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/cos_op.hpp0000644000176200001440000001463214536067013017463 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_COS_OP_INCLUDED # define CPPAD_COS_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file cos_op.hpp Forward and reverse mode calculations for z = cos(x). */ /*! Compute forward mode Taylor coefficient for result of op = CosOp. The C++ source code corresponding to this operation is \verbatim z = cos(x) \endverbatim The auxillary result is \verbatim y = sin(x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_cos_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* c = taylor + i_z * cap_order; Base* s = c - cap_order; // rest of this routine is identical for the following cases: // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op. // (except that there is a sign difference for the hyperbolic case). size_t k; if( p == 0 ) { s[0] = sin( x[0] ); c[0] = cos( x[0] ); p++; } for(size_t j = p; j <= q; j++) { s[j] = Base(0); c[j] = Base(0); for(k = 1; k <= j; k++) { s[j] += Base(k) * x[k] * c[j-k]; c[j] -= Base(k) * x[k] * s[j-k]; } s[j] /= Base(j); c[j] /= Base(j); } } /*! Compute forward mode Taylor coefficient for result of op = CosOp. The C++ source code corresponding to this operation is \verbatim z = cos(x) \endverbatim The auxillary result is \verbatim y = sin(x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_cos_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* c = taylor + i_z * num_taylor_per_var; Base* s = c - num_taylor_per_var; // rest of this routine is identical for the following cases: // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op // (except that there is a sign difference for the hyperbolic case). size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { s[m+ell] = Base(q) * x[m + ell] * c[0]; c[m+ell] = - Base(q) * x[m + ell] * s[0]; for(size_t k = 1; k < q; k++) { s[m+ell] += Base(k) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell]; c[m+ell] -= Base(k) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell]; } s[m+ell] /= Base(q); c[m+ell] /= Base(q); } } /*! Compute zero order forward mode Taylor coefficient for result of op = CosOp. The C++ source code corresponding to this operation is \verbatim z = cos(x) \endverbatim The auxillary result is \verbatim y = sin(x) \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_cos_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* c = taylor + i_z * cap_order; // called z in documentation Base* s = c - cap_order; // called y in documentation c[0] = cos( x[0] ); s[0] = sin( x[0] ); } /*! Compute reverse mode partial derivatives for result of op = CosOp. The C++ source code corresponding to this operation is \verbatim z = cos(x) \endverbatim The auxillary result is \verbatim y = sin(x) \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_cos_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* c = taylor + i_z * cap_order; // called z in doc Base* pc = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* s = c - cap_order; // called y in documentation Base* ps = pc - nc_partial; // If pc is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pc[i_d]); if( skip ) return; // rest of this routine is identical for the following cases: // reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op. size_t j = d; size_t k; while(j) { ps[j] /= Base(j); pc[j] /= Base(j); for(k = 1; k <= j; k++) { px[k] += ps[j] * Base(k) * c[j-k]; px[k] -= pc[j] * Base(k) * s[j-k]; ps[j-k] -= pc[j] * Base(k) * x[k]; pc[j-k] += ps[j] * Base(k) * x[k]; } --j; } px[0] += ps[0] * c[0]; px[0] -= pc[0] * s[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/sparse_binary_op.hpp0000644000176200001440000002147614536067013021544 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_BINARY_OP_INCLUDED # define CPPAD_SPARSE_BINARY_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sparse_binary_op.hpp Forward and reverse mode sparsity patterns for binary operators. */ /*! Forward mode Jacobian sparsity pattern for all binary operators. The C++ source code corresponding to a binary operation has the form \verbatim z = fun(x, y) \endverbatim where fun is a C++ binary function and both x and y are variables, or it has the form \verbatim z = x op y \endverbatim where op is a C++ binary unary operator and both x and y are variables. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e., z. \param arg \a arg[0] variable index corresponding to the left operand for this operator; i.e., x. \n \n arg[1] variable index corresponding to the right operand for this operator; i.e., y. \param sparsity \b Input: The set with index \a arg[0] in \a sparsity is the sparsity bit pattern for x. This identifies which of the independent variables the variable x depends on. \n \n \b Input: The set with index \a arg[1] in \a sparsity is the sparsity bit pattern for y. This identifies which of the independent variables the variable y depends on. \n \n \b Output: The set with index \a i_z in \a sparsity is the sparsity bit pattern for z. This identifies which of the independent variables the variable z depends on. \par Checked Assertions: \li \a arg[0] < \a i_z \li \a arg[1] < \a i_z */ template inline void forward_sparse_jacobian_binary_op( size_t i_z , const addr_t* arg , Vector_set& sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); sparsity.binary_union(i_z, arg[0], arg[1], sparsity); return; } /*! Reverse mode Jacobian sparsity pattern for all binary operators. The C++ source code corresponding to a unary operation has the form \verbatim z = fun(x, y) \endverbatim where fun is a C++ unary function and x and y are variables, or it has the form \verbatim z = x op y \endverbatim where op is a C++ bianry operator and x and y are variables. This routine is given the sparsity patterns for a function G(z, y, x, ... ) and it uses them to compute the sparsity patterns for \verbatim H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ] \endverbatim \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e., z. \param arg \a arg[0] variable index corresponding to the left operand for this operator; i.e., x. \n \n arg[1] variable index corresponding to the right operand for this operator; i.e., y. \param sparsity The set with index \a i_z in \a sparsity is the sparsity pattern for z corresponding ot the function G. \n \n The set with index \a arg[0] in \a sparsity is the sparsity pattern for x. On input, it corresponds to the function G, and on output it corresponds to H. \n \n The set with index \a arg[1] in \a sparsity is the sparsity pattern for y. On input, it corresponds to the function G, and on output it corresponds to H. \n \n \par Checked Assertions: \li \a arg[0] < \a i_z \li \a arg[1] < \a i_z */ template inline void reverse_sparse_jacobian_binary_op( size_t i_z , const addr_t* arg , Vector_set& sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); sparsity.binary_union(arg[0], arg[0], i_z, sparsity); sparsity.binary_union(arg[1], arg[1], i_z, sparsity); return; } /*! Reverse mode Hessian sparsity pattern for add and subtract operators. The C++ source code corresponding to a unary operation has the form \verbatim z = x op y \endverbatim where op is + or - and x, y are variables. \copydetails reverse_sparse_hessian_binary_op */ template inline void reverse_sparse_hessian_addsub_op( size_t i_z , const addr_t* arg , bool* jac_reverse , Vector_set& for_jac_sparsity , Vector_set& rev_hes_sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity); rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity); jac_reverse[arg[0]] |= jac_reverse[i_z]; jac_reverse[arg[1]] |= jac_reverse[i_z]; return; } /*! Reverse mode Hessian sparsity pattern for multiplication operator. The C++ source code corresponding to a unary operation has the form \verbatim z = x * y \endverbatim where x and y are variables. \copydetails reverse_sparse_hessian_binary_op */ template inline void reverse_sparse_hessian_mul_op( size_t i_z , const addr_t* arg , bool* jac_reverse , Vector_set& for_jac_sparsity , Vector_set& rev_hes_sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity); rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity); if( jac_reverse[i_z] ) { rev_hes_sparsity.binary_union( arg[0], arg[0], arg[1], for_jac_sparsity); rev_hes_sparsity.binary_union( arg[1], arg[1], arg[0], for_jac_sparsity); } jac_reverse[arg[0]] |= jac_reverse[i_z]; jac_reverse[arg[1]] |= jac_reverse[i_z]; return; } /*! Reverse mode Hessian sparsity pattern for division operator. The C++ source code corresponding to a unary operation has the form \verbatim z = x / y \endverbatim where x and y are variables. \copydetails reverse_sparse_hessian_binary_op */ template inline void reverse_sparse_hessian_div_op( size_t i_z , const addr_t* arg , bool* jac_reverse , Vector_set& for_jac_sparsity , Vector_set& rev_hes_sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity); rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity); if( jac_reverse[i_z] ) { rev_hes_sparsity.binary_union( arg[0], arg[0], arg[1], for_jac_sparsity); rev_hes_sparsity.binary_union( arg[1], arg[1], arg[0], for_jac_sparsity); rev_hes_sparsity.binary_union( arg[1], arg[1], arg[1], for_jac_sparsity); } jac_reverse[arg[0]] |= jac_reverse[i_z]; jac_reverse[arg[1]] |= jac_reverse[i_z]; return; } /*! Reverse mode Hessian sparsity pattern for power function. The C++ source code corresponding to a unary operation has the form \verbatim z = pow(x, y) \endverbatim where x and y are variables. \copydetails reverse_sparse_hessian_binary_op */ template inline void reverse_sparse_hessian_pow_op( size_t i_z , const addr_t* arg , bool* jac_reverse , Vector_set& for_jac_sparsity , Vector_set& rev_hes_sparsity ) { // check assumptions CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity); rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity); if( jac_reverse[i_z] ) { rev_hes_sparsity.binary_union( arg[0], arg[0], arg[0], for_jac_sparsity); rev_hes_sparsity.binary_union( arg[0], arg[0], arg[1], for_jac_sparsity); rev_hes_sparsity.binary_union( arg[1], arg[1], arg[0], for_jac_sparsity); rev_hes_sparsity.binary_union( arg[1], arg[1], arg[1], for_jac_sparsity); } // I cannot think of a case where this is necessary, but it including // it makes it like the other cases. jac_reverse[arg[0]] |= jac_reverse[i_z]; jac_reverse[arg[1]] |= jac_reverse[i_z]; return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/cskip_op.hpp0000644000176200001440000001152014536067013020001 0ustar liggesusers// $Id$ # ifndef CPPAD_CSKIP_OP_INCLUDED # define CPPAD_CSKIP_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file cskip_op.hpp Zero order forward mode set which operations to skip. */ /*! Zero order forward mode execution of op = CSkipOp. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param i_z variable index corresponding to the result of the previous operation. This is used for error checking. To be specific, the left and right operands for the CExpOp operation must have indexes less than or equal this value. \param arg [in] \n \a arg[0] is static cast to size_t from the enum type \verbatim enum CompareOp { CompareLt, CompareLe, CompareEq, CompareGe, CompareGt, CompareNe } \endverbatim for this operation. Note that arg[0] cannot be equal to CompareNe. \n \n \a arg[1] & 1 \n If this is zero, left is a a parameter. Otherwise it is a variable. \n \n \a arg[1] & 2 \n If this is zero, right is a parameter. Otherwise it is a variable. \n \a arg[2] is the index corresponding to left in comparision. \n \a arg[3] is the index corresponding to right in comparision. \n \a arg[4] is the number of operations to skip if the comparision result is true. \n \a arg[5] is the number of operations to skip if the comparision result is false. \n arg[5+i] for i = 1 , ... , arg[4] are the operations to skip if the comparision result is true. \n arg[5+arg[4]+i] for i = 1 , ... , arg[5] are the operations to skip if the comparision result is false. \param num_par [in] is the total number of values in the vector \a parameter. \param parameter [in] If left is a parameter, parameter [ arg[2] ] is its value. If right is a parameter, parameter [ arg[3] ] is its value. \param cap_order [in] number of columns in the matrix containing the Taylor coefficients. \param taylor [in] If left is a variable, taylor [ arg[2] * cap_order + 0 ] is the zeroth order Taylor coefficient corresponding to left. If right is a variable, taylor [ arg[3] * cap_order + 0 ] is the zeroth order Taylor coefficient corresponding to right. \param \cskip_op [in,out] is vector specifying which operations are at this point are know to be unecessary and can be skipped. This is both an input and an output. */ template inline void forward_cskip_op_0( size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , Base* taylor , bool* cskip_op ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < size_t(CompareNe) ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); Base left, right; if( arg[1] & 1 ) { // If varialbe arg[2] <= i_z, it has already been computed, // but it will be skipped for higher orders. left = taylor[ arg[2] * cap_order + 0 ]; CPPAD_ASSERT_UNKNOWN( IdenticalPar(left) ); } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); left = parameter[ arg[2] ]; CPPAD_ASSERT_UNKNOWN( IdenticalPar(left) ); } if( arg[1] & 2 ) { // If varialbe arg[3] <= i_z, it has already been computed, // but it will be skipped for higher orders. right = taylor[ arg[3] * cap_order + 0 ]; CPPAD_ASSERT_UNKNOWN( IdenticalPar(right) ); } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); right = parameter[ arg[3] ]; CPPAD_ASSERT_UNKNOWN( IdenticalPar(right) ); } // initialize to avoid compiler warning bool true_case = false; Base diff = left - right; switch( CompareOp( arg[0] ) ) { case CompareLt: true_case = LessThanZero(diff); break; case CompareLe: true_case = LessThanOrZero(diff); break; case CompareEq: true_case = IdenticalZero(diff); break; case CompareGe: true_case = GreaterThanOrZero(diff); break; case CompareGt: true_case = GreaterThanZero(diff); break; case CompareNe: true_case = ! IdenticalZero(diff); break; default: CPPAD_ASSERT_UNKNOWN(false); } if( true_case ) { for(size_t i = 0; i < size_t(arg[4]); i++) cskip_op[ arg[6+i] ] = true; } else { for(size_t i = 0; i < size_t(arg[5]); i++) cskip_op[ arg[6+arg[4]+i] ] = true; } return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/convert.hpp0000644000176200001440000000223514536067013017655 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_CONVERT_INCLUDED # define CPPAD_CONVERT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Convert$$ $spell $$ $index convert, from AD$$ $index AD, convert from$$ $section Conversion and I/O of AD Objects$$ $children% cppad/local/value.hpp% cppad/local/integer.hpp% cppad/local/ad_io.hpp% cppad/local/print_for.hpp% cppad/local/var2par.hpp %$$ $table $rref Value$$ $rref Integer$$ $rref ad_output$$ $rref PrintFor$$ $rref Var2Par$$ $tend $end */ # include # include # include # include # include # endif TMB/inst/include/cppad/local/rev_hes_sweep.hpp0000644000176200001440000005645414536067013021047 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_REV_HES_SWEEP_INCLUDED # define CPPAD_REV_HES_SWEEP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file rev_hes_sweep.hpp Compute Reverse mode Hessian sparsity patterns. */ /*! \def CPPAD_REV_HES_SWEEP_TRACE This value is either zero or one. Zero is the normal operational value. If it is one, a trace of every rev_hes_sweep computation is printed. */ # define CPPAD_REV_HES_SWEEP_TRACE 0 /*! Given the forward Jacobian sparsity pattern for all the variables, and the reverse Jacobian sparsity pattern for the dependent variables, RevHesSweep computes the Hessian sparsity pattern for all the independent variables. \tparam Base base type for the operator; i.e., this operation sequence was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param n is the number of independent variables on the tape. \param numvar is the total number of variables on the tape; i.e., \a play->num_var_rec(). This is also the number of rows in the entire sparsity pattern \a rev_hes_sparse. \param play The information stored in \a play is a recording of the operations corresponding to a function \f[ F : {\bf R}^n \rightarrow {\bf R}^m \f] where \f$ n \f$ is the number of independent variables and \f$ m \f$ is the number of dependent variables. The object \a play is effectly constant. It is not declared const because while playing back the tape the object \a play holds information about the currentl location with in the tape and this changes during playback. \param for_jac_sparse For i = 0 , ... , \a numvar - 1, (for all the variables on the tape), the forward Jacobian sparsity pattern for the variable with index i corresponds to the set with index i in \a for_jac_sparse. \param RevJac \b Input: For i = 0, ... , \a numvar - 1 the if the variable with index i on the tape is an dependent variable and included in the Hessian, \a RevJac[ i ] is equal to true, otherwise it is equal to false. \n \n \b Output: The values in \a RevJac upon return are not specified; i.e., it is used for temporary work space. \param rev_hes_sparse The reverse Hessian sparsity pattern for the variable with index i corresponds to the set with index i in \a rev_hes_sparse. \n \n \b Input: For i = 0 , ... , \a numvar - 1 the reverse Hessian sparsity pattern for the variable with index i is empty. \n \n \b Output: For j = 1 , ... , \a n, the reverse Hessian sparsity pattern for the independent dependent variable with index (j-1) is given by the set with index j in \a rev_hes_sparse. The values in the rest of \a rev_hes_sparse are not specified; i.e., they are used for temporary work space. */ template void RevHesSweep( size_t n, size_t numvar, player *play, Vector_set& for_jac_sparse, // should be const bool* RevJac, Vector_set& rev_hes_sparse ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); size_t i, j, k; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // upper limit exclusive for set elements size_t limit = rev_hes_sparse.end(); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit ); // check number of sets match CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == rev_hes_sparse.n_set() ); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index for the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparse; vecad_sparse.resize(num_vecad_vec, limit); pod_vector vecad_ind; pod_vector vecad_jac; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); vecad_jac.extend(num_vecad_vec); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set vecad_ind to proper index for this VecAD vecad_ind[j] = i; // make all other values for this vector invalid for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // start of next VecAD j += length + 1; // initialize this vector's reverse jacobian value vecad_jac[i] = false; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // work space used by UserOp. vector user_ix; // variable indices for argument vector x typedef std::set size_set; size_set::iterator set_itr; // iterator for a standard set size_set::iterator set_end; // end of iterator sequence vector< size_set > set_r; // forward Jacobian sparsity for x vector< size_set > set_u; // reverse Hessian sparsity for y vector< size_set > set_v; // reverse Hessian sparsity for x // vector bool_r; // bool forward Jacobian sparsity for x vector bool_u; // bool reverse Hessian sparsity for y vector bool_v; // bool reverse Hessian sparsity for x // vector user_vx; // which components of x are variables vector user_s; // reverse Jacobian sparsity for y vector user_t; // reverse Jacobian sparsity for x const size_t user_q = limit; // maximum element plus one size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // user's atomic op calculator bool user_bool = false; // use bool or set sparsity ? # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_end; // Initialize play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REV_HES_SWEEP_TRACE Rcout << std::endl; CppAD::vectorBool zf_value(limit); CppAD::vectorBool zh_value(limit); # endif bool more_operators = true; while(more_operators) { // next op play->reverse_next(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) more_operators = false; break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_csum(op, arg, i_op, i_var); reverse_sparse_hessian_csum_op( i_var, arg, RevJac, rev_hes_sparse ); break; // ------------------------------------------------- case CExpOp: reverse_sparse_hessian_cond_op( i_var, arg, num_par, RevJac, rev_hes_sparse ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) // derivativve is identically zero break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_div_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[0] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1) // Z is already defined break; // ------------------------------------------------- case LdpOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case LdvOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_mul_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_pow_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); break; // ------------------------------------------------- case SignOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); // Derivative is identiaclly zero break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case StppOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StpvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case StvpOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StvvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_end ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_bool = user_atom->sparsity() == atomic_base::bool_sparsity_enum; user_ix.resize(user_n); user_vx.resize(user_n); user_s.resize(user_m); user_t.resize(user_n); // simpler to initialize all sparsity patterns as empty for(i = 0; i < user_m; i++) user_s[i] = false; for(i = 0; i < user_n; i++) user_t[i] = false; if( user_bool ) { bool_r.resize(user_n * user_q); bool_u.resize(user_m * user_q); bool_v.resize(user_n * user_q); // simpler to initialize all patterns as empty for(i = 0; i < user_m; i++) { for(j = 0; j < user_q; j++) bool_u[ i * user_q + j] = false; } for(i = 0; i < user_n; i++) { for(j = 0; j < user_q; j++) { bool_r[ i * user_q + j] = false; bool_v[ i * user_q + j] = false; } } } else { set_r.resize(user_n); set_u.resize(user_m); set_v.resize(user_n); for(i = 0; i < user_m; i++) set_u[i].clear(); for(i = 0; i < user_n; i++) { set_r[i].clear(); set_v[i].clear(); } } user_j = user_n; user_i = user_m; user_state = user_ret; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); user_state = user_end; // call users function for this operation user_atom->set_id(user_id); # ifdef NDEBUG if( user_bool ) user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, bool_r, bool_u, bool_v ); else user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, set_r, set_u, set_v ); # else if( user_bool ) user_ok = user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, bool_r, bool_u, bool_v ); else user_ok = user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, set_r, set_u, set_v ); if( ! user_ok ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base.rev_sparse_hes: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(i = 0; i < user_n; i++) if( user_ix[i] > 0 ) { size_t i_x = user_ix[i]; if( user_t[i] ) RevJac[i_x] = true; if( user_bool ) { for(j = 0; j < user_q; j++) if( bool_v[ i * user_q + j ] ) rev_hes_sparse.add_element(i_x, j); } else { set_itr = set_v[i].begin(); set_end = set_v[i].end(); while( set_itr != set_end ) rev_hes_sparse.add_element(i_x, *set_itr++); } } } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_j; user_ix[user_j] = 0; user_vx[user_j] = false; if( user_j == 0 ) user_state = user_start; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); --user_j; user_ix[user_j] = arg[0]; user_vx[user_j] = true; for_jac_sparse.begin(arg[0]); i = for_jac_sparse.next_element(); while( i < user_q ) { if( user_bool ) bool_r[ user_j * user_q + i ] = true; else set_r[user_j].insert(i); i = for_jac_sparse.next_element(); } if( user_j == 0 ) user_state = user_start; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_i; if( user_i == 0 ) user_state = user_arg; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); --user_i; if( RevJac[i_var] ) { user_s[user_i] = true; } rev_hes_sparse.begin(i_var); j = rev_hes_sparse.next_element(); while( j < user_q ) { if( user_bool ) bool_u[user_i * user_q + j] = true; else set_u[user_i].insert(j); j = rev_hes_sparse.next_element(); } if( user_i == 0 ) user_state = user_arg; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_REV_HES_SWEEP_TRACE for(j = 0; j < limit; j++) { zf_value[j] = false; zh_value[j] = false; } for_jac_sparse.begin(i_var);; j = for_jac_sparse.next_element();; while( j < limit ) { zf_value[j] = true; j = for_jac_sparse.next_element(); } rev_hes_sparse.begin(i_var);; j = rev_hes_sparse.next_element();; while( j < limit ) { zh_value[j] = true; j = rev_hes_sparse.next_element(); } printOp( Rcout, play, i_op, i_var, op, arg ); // should also print RevJac[i_var], but printOpResult does not // yet allow for this if( NumRes(op) > 0 && op != BeginOp ) printOpResult( Rcout, 1, &zf_value, 1, &zh_value ); Rcout << std::endl; } Rcout << std::endl; # else } # endif // values corresponding to BeginOp CPPAD_ASSERT_UNKNOWN( i_op == 0 ); CPPAD_ASSERT_UNKNOWN( i_var == 0 ); return; } } // END_CPPAD_NAMESPACE // preprocessor symbols that are local to this file # undef CPPAD_REV_HES_SWEEP_TRACE # endif TMB/inst/include/cppad/local/print_for.hpp0000644000176200001440000001370114536067013020177 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_PRINT_FOR_INCLUDED # define CPPAD_PRINT_FOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin PrintFor$$ $spell pos var VecAD std Rcout const $$ $index print, forward mode$$ $index forward, mode print$$ $index text, output$$ $index output, text$$ $index debug, forward mode$$ $index forward, debug$$ $section Printing AD Values During Forward Mode$$ $head Syntax$$ $icode%f%.Forward(0, %x%) %$$ $codei%PrintFor(%before%, %var%) %$$ $codei%PrintFor(%pos%, %before%, %var%, %after%) %$$ $head Purpose$$ The $cref/zero order forward/forward_zero/$$ mode command $codei% %f%.Forward(0, %x%) %$$ assigns the $cref/independent variable/glossary/Tape/Independent Variable/$$ vector equal to $icode x$$. It then computes a value for all of the dependent variables in the $cref/operation sequence/glossary/Operation/Sequence/$$ corresponding to $icode f$$. Putting a $code PrintFor$$ in the operation sequence will cause the value of $icode var$$, corresponding to $icode x$$, to be printed during zero order forward operations. $head f.Forward(0, x)$$ The objects $icode f$$, $icode x$$, and the purpose for this operation, are documented in $cref Forward$$. $head pos$$ If present, the argument $icode pos$$ has one of the following prototypes $codei% const AD<%Base%>& %pos% const VecAD<%Base%>::reference& %pos% %$$ In this case the text and $icode var$$ will be printed if and only if $icode pos$$ is not greater than zero and a finite number. $head before$$ The argument $icode before$$ has prototype $codei% const char* %before% %$$ This text is written to $code Rcout$$ before $icode var$$. $head var$$ The argument $icode var$$ has one of the following prototypes $codei% const AD<%Base%>& %var% const VecAD<%Base%>::reference& %var% %$$ The value of $icode var$$, that corresponds to $icode x$$, is written to $code Rcout$$ during the execution of $codei% %f%.Forward(0, %x%) %$$ Note that $icode var$$ may be a $cref/variable/glossary/Variable/$$ or $cref/parameter/glossary/Parameter/$$. (A parameters value does not depend on the value of the independent variable vector $icode x$$.) $head after$$ The argument $icode after$$ has prototype $codei% const char* %after% %$$ This text is written to $code Rcout$$ after $icode var$$. $head Discussion$$ This is helpful for understanding why tape evaluations have trouble. For example, if one of the operations in $icode f$$ is $codei%log(%var%)%$$ and $icode%var% <= 0%$$, the corresponding result will be $cref nan$$. $head Alternative$$ The $cref ad_output$$ section describes the normal printing of values; i.e., printing when the corresponding code is executed. $head Example$$ $children% print_for/print_for.cpp% example/print_for.cpp %$$ The program $cref print_for_Rcout.cpp$$ is an example and test that prints to standard output. The output of this program states the conditions for passing and failing the test. The function $cref print_for_string.cpp$$ is an example and test that prints to an standard string stream. This function automatically check for correct output. $end ------------------------------------------------------------------------------ */ # include namespace CppAD { template void PrintFor(const AD& pos, const char *before, const AD& var, const char* after) { CPPAD_ASSERT_NARG_NRES(PriOp, 5, 0); // check for case where we are not recording operations ADTape* tape = AD::tape_ptr(); if( tape == CPPAD_NULL ) return; CPPAD_ASSERT_KNOWN( std::strlen(before) <= 1000 , "PrintFor: length of before is greater than 1000 characters" ); CPPAD_ASSERT_KNOWN( std::strlen(after) <= 1000 , "PrintFor: length of after is greater than 1000 characters" ); size_t ind0, ind1, ind2, ind3, ind4; // ind[0] = base 2 representation of the value [Var(pos), Var(var)] ind0 = 0; // ind[1] = address for pos if( Parameter(pos) ) ind1 = tape->Rec_.PutPar(pos.value_); else { ind0 += 1; ind1 = pos.taddr_; } // ind[2] = address of before ind2 = tape->Rec_.PutTxt(before); // ind[3] = address for var if( Parameter(var) ) ind3 = tape->Rec_.PutPar(var.value_); else { ind0 += 2; ind3 = var.taddr_; } // ind[4] = address of after ind4 = tape->Rec_.PutTxt(after); // put the operator in the tape tape->Rec_.PutArg(ind0, ind1, ind2, ind3, ind4); tape->Rec_.PutOp(PriOp); } // Fold all other cases into the case above template void PrintFor(const char* before, const AD& var) { PrintFor(AD(0), before, var, "" ); } // template void PrintFor(const char* before, const VecAD_reference& var) { PrintFor(AD(0), before, var.ADBase(), "" ); } // template void PrintFor( const VecAD_reference& pos , const char *before , const VecAD_reference& var , const char *after ) { PrintFor(pos.ADBase(), before, var.ADBase(), after); } // template void PrintFor( const VecAD_reference& pos , const char *before , const AD& var , const char *after ) { PrintFor(pos.ADBase(), before, var, after); } // template void PrintFor( const AD& pos , const char *before , const VecAD_reference& var , const char *after ) { PrintFor(pos, before, var.ADBase(), after); } } # endif TMB/inst/include/cppad/local/op.hpp0000644000176200001440000000353014536067013016612 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_OP_INCLUDED # define CPPAD_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ // used by the sparse operators # include // operations # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # endif TMB/inst/include/cppad/local/atan2.hpp0000644000176200001440000000660714536067013017211 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ATAN2_INCLUDED # define CPPAD_ATAN2_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin atan2$$ $spell Vec CppAD namespace std atan const $$ $index tan, AD inverse$$ $index inverse, AD tan$$ $index atan2, AD$$ $section AD Two Argument Inverse Tangent Function$$ $head Syntax$$ $icode%theta% = atan2(%y%, %x%)%$$ $head Purpose$$ Determines an angle $latex \theta \in [ - \pi , + \pi ]$$ such that $latex \[ \begin{array}{rcl} \sin ( \theta ) & = & y / \sqrt{ x^2 + y^2 } \\ \cos ( \theta ) & = & x / \sqrt{ x^2 + y^2 } \end{array} \] $$ $head y$$ The argument $icode y$$ has one of the following prototypes $codei% const AD<%Base%> &%y% const VecAD<%Base%>::reference &%y% %$$ $head x$$ The argument $icode x$$ has one of the following prototypes $codei% const AD<%Base%> &%x% const VecAD<%Base%>::reference &%x% %$$ $head theta$$ The result $icode theta$$ has prototype $codei% AD<%Base%> %theta% %$$ $head Operation Sequence$$ The AD of $icode Base$$ operation sequence used to calculate $icode theta$$ is $cref/independent/glossary/Operation/Independent/$$ of $icode x$$ and $icode y$$. $head Example$$ $children% example/atan2.cpp %$$ The file $cref atan2.cpp$$ contains an example and test of this function. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------- */ namespace CppAD { // BEGIN CppAD namespace inline float atan2(float x, float y) { return std::atan2(x, y); } inline double atan2(double x, double y) { return std::atan2(x, y); } // The code below is used as an example by the CondExp documentation. // BEGIN CondExp template AD atan2 (const AD &y, const AD &x) { AD alpha; AD beta; AD theta; AD zero(0.); AD pi2(2. * atan(1.)); AD pi(2. * pi2); AD ax = abs(x); AD ay = abs(y); // if( ax > ay ) // theta = atan(ay / ax); // else theta = pi2 - atan(ax / ay); alpha = atan(ay / ax); beta = pi2 - atan(ax / ay); theta = CondExpGt(ax, ay, alpha, beta); // use of CondExp // if( x <= 0 ) // theta = pi - theta; theta = CondExpLe(x, zero, pi - theta, theta); // use of CondExp // if( y <= 0 ) // theta = - theta; theta = CondExpLe(y, zero, -theta, theta); // use of CondExp return theta; } // END CondExp template inline AD atan2 (const VecAD_reference &y, const AD &x) { return atan2( y.ADBase() , x ); } template inline AD atan2 (const AD &y, const VecAD_reference &x) { return atan2( y , x.ADBase() ); } template inline AD atan2 (const VecAD_reference &y, const VecAD_reference &x) { return atan2( y.ADBase() , x.ADBase() ); } } // END CppAD namespace # endif TMB/inst/include/cppad/local/drivers.hpp0000644000176200001440000000253414536067013017655 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DRIVERS_INCLUDED # define CPPAD_DRIVERS_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-08 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Drivers$$ $spell $$ $index forward, easy driver$$ $index reverse, easy driver$$ $index easy, driver$$ $index driver, easy$$ $section First and Second Derivatives: Easy Drivers$$ $childtable% cppad/local/jacobian.hpp% cppad/local/for_one.hpp% cppad/local/rev_one.hpp% cppad/local/hessian.hpp% cppad/local/for_two.hpp% cppad/local/rev_two.hpp% cppad/local/sparse_jacobian.hpp% cppad/local/sparse_hessian.hpp %$$ $end */ # include # include # include # include # include # include # include # include # endif TMB/inst/include/cppad/local/fun_check.hpp0000644000176200001440000001336214536067013020125 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FUN_CHECK_INCLUDED # define CPPAD_FUN_CHECK_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin FunCheck$$ $spell exp bool const Taylor $$ $index FunCheck$$ $index check, ADFun$$ $index ADFun, check$$ $section Check an ADFun Sequence of Operations$$ $head Syntax$$ $icode%ok% = FunCheck(%f%, %g%, %x%, %r%, %a%)%$$ $pre $$ $bold See Also$$ $cref CompareChange$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. We use $latex G : B^n \rightarrow B^m$$ to denote the function corresponding to the C++ function object $icode g$$. This routine check if $latex \[ F(x) = G(x) \]$$ If $latex F(x) \neq G(x)$$, the $cref/operation sequence/glossary/Operation/Sequence/$$ corresponding to $icode f$$ does not represents the algorithm used by $icode g$$ to calculate values for $latex G$$ (see $cref/Discussion/FunCheck/Discussion/$$ below). $head f$$ The $code FunCheck$$ argument $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/Forward/FunCheck/FunCheck Uses Forward/$$ below). $head g$$ The $code FunCheck$$ argument $icode g$$ has prototype $codei% %Fun% &%g% %$$ ($icode Fun$$ is defined the properties of $icode g$$). The C++ function object $icode g$$ supports the syntax $codei% %y% = %g%(%x%) %$$ which computes $latex y = G(x)$$. $subhead x$$ The $icode g$$ argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ (see $cref/Vector/FunCheck/Vector/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. $head y$$ The $icode g$$ result $icode y$$ has prototype $codei% %Vector% %y% %$$ and its value is $latex G(x)$$. The size of $icode y$$ is equal to $icode m$$, the dimension of the $cref/range/seq_property/Range/$$ space for $icode f$$. $head x$$ The $code FunCheck$$ argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. This specifies that point at which to compare the values calculated by $icode f$$ and $icode G$$. $head r$$ The $code FunCheck$$ argument $icode r$$ has prototype $codei% const %Base% &%r% %$$ It specifies the relative error the element by element comparison of the value of $latex F(x)$$ and $latex G(x)$$. $head a$$ The $code FunCheck$$ argument $icode a$$ has prototype $codei% const %Base% &%a% %$$ It specifies the absolute error the element by element comparison of the value of $latex F(x)$$ and $latex G(x)$$. $head ok$$ The $code FunCheck$$ result $icode ok$$ has prototype $codei% bool %ok% %$$ It is true, if for $latex i = 0 , \ldots , m-1$$ either the relative error bound is satisfied $latex \[ | F_i (x) - G_i (x) | \leq r ( | F_i (x) | + | G_i (x) | ) \] $$ or the absolute error bound is satisfied $latex \[ | F_i (x) - G_i (x) | \leq a \] $$ It is false if for some $latex (i, j)$$ neither of these bounds is satisfied. $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Base$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head FunCheck Uses Forward$$ After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After $code FunCheck$$, the previous calls to $cref Forward$$ are undefined. $head Discussion$$ Suppose that the algorithm corresponding to $icode g$$ contains $codei% if( %x% >= 0 ) %y% = exp(%x%) else %y% = exp(-%x%) %$$ where $icode x$$ and $icode y$$ are $codei%AD%$$ objects. It follows that the AD of $code double$$ $cref/operation sequence/glossary/Operation/Sequence/$$ depends on the value of $icode x$$. If the sequence of operations stored in $icode f$$ corresponds to $icode g$$ with $latex x \geq 0$$, the function values computed using $icode f$$ when $latex x < 0$$ will not agree with the function values computed by $latex g$$. This is because the operation sequence corresponding to $icode g$$ changed (and hence the object $icode f$$ does not represent the function $latex G$$ for this value of $icode x$$). In this case, you probably want to re-tape the calculations performed by $icode g$$ with the $cref/independent variables/glossary/Tape/Independent Variable/$$ equal to the values in $icode x$$ (so AD operation sequence properly represents the algorithm for this value of independent variables). $head Example$$ $children% example/fun_check.cpp %$$ The file $cref fun_check.cpp$$ contains an example and test of this function. It returns true if it succeeds and false otherwise. $end --------------------------------------------------------------------------- */ namespace CppAD { template bool FunCheck( ADFun &f , Fun &g , const Vector &x , const Base &r , const Base &a ) { bool ok = true; size_t m = f.Range(); Vector yf = f.Forward(0, x); Vector yg = g(x); size_t i; for(i = 0; i < m; i++) ok &= NearEqual(yf[i], yg[i], r, a); return ok; } } # endif TMB/inst/include/cppad/local/recorder.hpp0000644000176200001440000004135214536067013020005 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_RECORDER_INCLUDED # define CPPAD_RECORDER_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file recorder.hpp File used to define the recorder class. */ /*! Class used to store an operation sequence while it is being recorded (the operation sequence is copied to the player class for playback). \tparam Base This is an AD< \a Base > operation sequence recording; i.e., it records operations of type AD< \a Base >. */ template class recorder { friend class player; private: /// operator index at which to abort recording with an error /// (do not abort when zero) size_t abort_op_index_; /// offset for this thread in the static hash table const size_t thread_offset_; /// Number of variables in the recording. size_t num_var_rec_; /// Number vecad load operations (LdpOp or LdvOp) currently in recording. size_t num_load_op_rec_; /// The operators in the recording. pod_vector op_rec_; /// The VecAD indices in the recording. pod_vector vecad_ind_rec_; /// The argument indices in the recording pod_vector op_arg_rec_; /// The parameters in the recording. /// Note that Base may not be plain old data, so use false in consructor. pod_vector par_rec_; /// Character strings ('\\0' terminated) in the recording. pod_vector text_rec_; // ---------------------- Public Functions ----------------------------------- public: /// Default constructor recorder(void) : thread_offset_( thread_alloc::thread_num() * CPPAD_HASH_TABLE_SIZE ) , num_var_rec_(0) , num_load_op_rec_(0) , op_rec_( std::numeric_limits::max() ) , vecad_ind_rec_( std::numeric_limits::max() ) , op_arg_rec_( std::numeric_limits::max() ) , par_rec_( std::numeric_limits::max() ) , text_rec_( std::numeric_limits::max() ) { abort_op_index_ = 0; } /// Set the abort index void set_abort_op_index(size_t abort_op_index) { abort_op_index_ = abort_op_index; } /// Get the abort index size_t get_abort_op_index(void) { return abort_op_index_; } /// Destructor ~recorder(void) { } /*! Frees all information in recording. Frees the operation sequence store in this recording (the operation sequence is empty after this operation). The buffers used to store the current recording are returned to the system (so as to conserve on memory). */ void free(void) { num_var_rec_ = 0; num_load_op_rec_ = 0; op_rec_.free(); vecad_ind_rec_.free(); op_arg_rec_.free(); par_rec_.free(); text_rec_.free(); } /// Put next operator in the operation sequence. inline size_t PutOp(OpCode op); /// Put a vecad load operator in the operation sequence (special case) inline size_t PutLoadOp(OpCode op); /// Add a value to the end of the current vector of VecAD indices. inline size_t PutVecInd(size_t vec_ind); /// Find or add a parameter to the current vector of parameters. inline size_t PutPar(const Base &par); /// Put one operation argument index in the recording inline void PutArg(addr_t arg0); /// Put two operation argument index in the recording inline void PutArg(addr_t arg0, addr_t arg1); /// Put three operation argument index in the recording inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2); /// Put four operation argument index in the recording inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3); /// Put five operation argument index in the recording inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3, addr_t arg4); /// Put six operation argument index in the recording inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3, addr_t arg4, addr_t arg5); // Reserve space for a specified number of arguments inline size_t ReserveArg(size_t n_arg); // Replace an argument value void ReplaceArg(size_t i_arg, size_t value); /// Put a character string in the text for this recording. inline size_t PutTxt(const char *text); /// Number of variables currently stored in the recording. size_t num_var_rec(void) const { return num_var_rec_; } /// Number of LdpOp and LdvOp operations currently in the recording. size_t num_load_op_rec(void) const { return num_load_op_rec_; } /// Number of operators currently stored in the recording. size_t num_op_rec(void) const { return op_rec_.size(); } /// Approximate amount of memory used by the recording size_t Memory(void) const { return op_rec_.capacity() * sizeof(CPPAD_OP_CODE_TYPE) + vecad_ind_rec_.capacity() * sizeof(size_t) + op_arg_rec_.capacity() * sizeof(addr_t) + par_rec_.capacity() * sizeof(Base) + text_rec_.capacity() * sizeof(char); } }; /*! Put next operator in the operation sequence. This sets the op code for the next operation in this recording. This call must be followed by putting the corresponding \verbatim NumArg(op) \endverbatim argument indices in the recording. \param op Is the op code corresponding to the the operation that is being recorded (which must not be LdpOp or LdvOp). \return The return value is the index of the primary (last) variable corresponding to the result of this operation. The number of variables corresponding to the operation is given by \verbatim NumRes(op) \endverbatim With each call to PutOp or PutLoadOp, the return index increases by the number of variables corresponding to the call. This index starts at zero after the default constructor and after each call to Erase. */ template inline size_t recorder::PutOp(OpCode op) { size_t i = op_rec_.extend(1); CPPAD_ASSERT_KNOWN( (abort_op_index_ == 0) || (abort_op_index_ != i), "Operator index equals abort_op_index in Independent" ); op_rec_[i] = static_cast(op); CPPAD_ASSERT_UNKNOWN( op_rec_.size() == i + 1 ); CPPAD_ASSERT_UNKNOWN( (op != LdpOp) & (op != LdvOp) ); // first operator should be a BeginOp and NumRes( BeginOp ) > 0 num_var_rec_ += NumRes(op); CPPAD_ASSERT_UNKNOWN( num_var_rec_ > 0 ); return num_var_rec_ - 1; } /*! Put next LdpOp or LdvOp operator in operation sequence (special cases). This sets the op code for the next operation in this recording. This call must be followed by putting the corresponding \verbatim NumArg(op) \endverbatim argument indices in the recording. \param op Is the op code corresponding to the the operation that is being recorded (which must be LdpOp or LdvOp). \return The return value is the index of the primary (last) variable corresponding to the result of this operation. The number of variables corresponding to the operation is given by \verbatim NumRes(op) \endverbatim which must be one for this operation. With each call to PutLoadOp or PutOp, the return index increases by the number of variables corresponding to this call to the call. This index starts at zero after the default constructor and after each call to Erase. \par num_load_op_rec() The return value for num_load_op_rec() increases by one after each call to this function (and starts at zero after the default constructor or Erase). */ template inline size_t recorder::PutLoadOp(OpCode op) { size_t i = op_rec_.extend(1); CPPAD_ASSERT_KNOWN( (abort_op_index_ == 0) || (abort_op_index_ != i), "This is the abort operator index specified by " "Independent(x, abort_op_index)." ); op_rec_[i] = static_cast(op); CPPAD_ASSERT_UNKNOWN( op_rec_.size() == i + 1 ); CPPAD_ASSERT_UNKNOWN( (op == LdpOp) | (op == LdvOp) ); // first operator should be a BeginOp and NumRes( BeginOp ) > 0 num_var_rec_ += NumRes(op); CPPAD_ASSERT_UNKNOWN( num_var_rec_ > 0 ); // count this vecad load operation num_load_op_rec_++; return num_var_rec_ - 1; } /*! Add a value to the end of the current vector of VecAD indices. For each VecAD vector, this routine is used to store the length of the vector followed by the parameter index corresponding to each value in the vector. This value for the elements of the VecAD vector corresponds to the beginning of the operation sequence. \param vec_ind is the index to be palced at the end of the vector of VecAD indices. \return is the index in the vector of VecAD indices corresponding to this value. This index starts at zero after the recorder default constructor and after each call to Erase. It increments by one for each call to PutVecInd.. */ template inline size_t recorder::PutVecInd(size_t vec_ind) { size_t i = vecad_ind_rec_.extend(1); vecad_ind_rec_[i] = vec_ind; CPPAD_ASSERT_UNKNOWN( vecad_ind_rec_.size() == i + 1 ); return i; } /*! Find or add a parameter to the current vector of parameters. \param par is the parameter to be found or placed in the vector of parameters. \return is the index in the parameter vector corresponding to this parameter value. This value is not necessarily placed at the end of the vector (because values that are identically equal may be reused). */ template size_t recorder::PutPar(const Base &par) { static size_t hash_table[CPPAD_HASH_TABLE_SIZE * CPPAD_MAX_NUM_THREADS]; size_t i; size_t code; CPPAD_ASSERT_UNKNOWN( thread_offset_ / CPPAD_HASH_TABLE_SIZE == thread_alloc::thread_num() ); // get hash code for this value code = static_cast( hash_code(par) ); CPPAD_ASSERT_UNKNOWN( code < CPPAD_HASH_TABLE_SIZE ); // If we have a match, return the parameter index i = hash_table[code + thread_offset_]; if( i < par_rec_.size() && IdenticalEqualPar(par_rec_[i], par) ) return i; // place a new value in the table i = par_rec_.extend(1); par_rec_[i] = par; CPPAD_ASSERT_UNKNOWN( par_rec_.size() == i + 1 ); // make the hash code point to this new value hash_table[code + thread_offset_] = i; // return the parameter index return i; } // -------------------------- PutArg -------------------------------------- /*! Prototype for putting operation argument indices in the recording. The following syntax \verbatim rec.PutArg(arg0) rec.PutArg(arg0, arg1) . . . rec.PutArg(arg0, arg1, ..., arg5) \endverbatim places the values passed to PutArg at the current end of the operation argument indices for the recording. \a arg0 comes before \a arg1, etc. The proper number of operation argument indices corresponding to the operation code op is given by \verbatim NumArg(op) \endverbatim The number of the operation argument indices starts at zero after the default constructor and each call to Erase. It increases by the number of indices placed by each call to PutArg. */ inline void prototype_put_arg(void) { // This routine should not be called CPPAD_ASSERT_UNKNOWN(false); } /*! Put one operation argument index in the recording \param arg0 The operation argument index \copydetails prototype_put_arg */ template inline void recorder::PutArg(addr_t arg0) { size_t i = op_arg_rec_.extend(1); op_arg_rec_[i] = static_cast( arg0 ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 ); } /*! Put two operation argument index in the recording \param arg0 First operation argument index. \param arg1 Second operation argument index. \copydetails prototype_put_arg */ template inline void recorder::PutArg(addr_t arg0, addr_t arg1) { size_t i = op_arg_rec_.extend(2); op_arg_rec_[i++] = static_cast( arg0 ); op_arg_rec_[i] = static_cast( arg1 ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 ); } /*! Put three operation argument index in the recording \param arg0 First operation argument index. \param arg1 Second operation argument index. \param arg2 Third operation argument index. \copydetails prototype_put_arg */ template inline void recorder::PutArg(addr_t arg0, addr_t arg1, addr_t arg2) { size_t i = op_arg_rec_.extend(3); op_arg_rec_[i++] = static_cast( arg0 ); op_arg_rec_[i++] = static_cast( arg1 ); op_arg_rec_[i] = static_cast( arg2 ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 ); } /*! Put four operation argument index in the recording \param arg0 First operation argument index. \param arg1 Second operation argument index. \param arg2 Third operation argument index. \param arg3 Fourth operation argument index. \copydetails prototype_put_arg */ template inline void recorder::PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3) { size_t i = op_arg_rec_.extend(4); op_arg_rec_[i++] = static_cast( arg0 ); op_arg_rec_[i++] = static_cast( arg1 ); op_arg_rec_[i++] = static_cast( arg2 ); op_arg_rec_[i] = static_cast( arg3 ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 ); } /*! Put five operation argument index in the recording \param arg0 First operation argument index. \param arg1 Second operation argument index. \param arg2 Third operation argument index. \param arg3 Fourth operation argument index. \param arg4 Fifth operation argument index. \copydetails prototype_put_arg */ template inline void recorder::PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3, addr_t arg4) { size_t i = op_arg_rec_.extend(5); op_arg_rec_[i++] = static_cast( arg0 ); op_arg_rec_[i++] = static_cast( arg1 ); op_arg_rec_[i++] = static_cast( arg2 ); op_arg_rec_[i++] = static_cast( arg3 ); op_arg_rec_[i] = static_cast( arg4 ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 ); } /*! Put six operation argument index in the recording \param arg0 First operation argument index. \param arg1 Second operation argument index. \param arg2 Third operation argument index. \param arg3 Fourth operation argument index. \param arg4 Fifth operation argument index. \param arg5 Sixth operation argument index. \copydetails prototype_put_arg */ template inline void recorder::PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3, addr_t arg4, addr_t arg5) { size_t i = op_arg_rec_.extend(6); op_arg_rec_[i++] = static_cast( arg0 ); op_arg_rec_[i++] = static_cast( arg1 ); op_arg_rec_[i++] = static_cast( arg2 ); op_arg_rec_[i++] = static_cast( arg3 ); op_arg_rec_[i++] = static_cast( arg4 ); op_arg_rec_[i] = static_cast( arg5 ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 ); } // -------------------------------------------------------------------------- /*! Reserve space for arguments, but delay placing values there. \param n_arg number of arguements to reserve space for \return is the index in the argument vector corresponding to the first of the arguments being reserved. */ template inline size_t recorder::ReserveArg(size_t n_arg) { size_t i = op_arg_rec_.extend(n_arg); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + n_arg ); return i; } /*! \brief Replace an argument value in the recording (intended to fill in reserved values). \param i_arg is the index, in argument vector, for the value that is replaced. \param value is the new value for the argument with the specified index. */ template inline void recorder::ReplaceArg(size_t i_arg, size_t value) { op_arg_rec_[i_arg] = static_cast( value ); } // -------------------------------------------------------------------------- /*! Put a character string in the text for this recording. \param text is a '\\0' terminated character string that is to be put in the vector of characters corresponding to this recording. The terminator '\\0' will be included. \return is the offset with in the text vector for this recording at which the character string starts. */ template inline size_t recorder::PutTxt(const char *text) { // determine length of the text including terminating '\0' size_t n = 0; while( text[n] != '\0' ) n++; CPPAD_ASSERT_UNKNOWN( n <= 1000 ); n++; CPPAD_ASSERT_UNKNOWN( text[n-1] == '\0' ); // copy text including terminating '\0' size_t i = text_rec_.extend(n); size_t j; for(j = 0; j < n; j++) text_rec_[i + j] = text[j]; CPPAD_ASSERT_UNKNOWN( text_rec_.size() == i + n ); return i; } // ------------------------------------------------------------------------- } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/log_op.hpp0000644000176200001440000001153614536067013017460 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_LOG_OP_INCLUDED # define CPPAD_LOG_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file log_op.hpp Forward and reverse mode calculations for z = log(x). */ /*! Compute forward mode Taylor coefficient for result of op = LogOp. The C++ source code corresponding to this operation is \verbatim z = log(x) \endverbatim \copydetails forward_unary1_op */ template inline void forward_log_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { size_t k; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; if( p == 0 ) { z[0] = log( x[0] ); p++; if( q == 0 ) return; } if ( p == 1 ) { z[1] = x[1] / x[0]; p++; } for(size_t j = p; j <= q; j++) { z[j] = -z[1] * x[j-1]; for(k = 2; k < j; k++) z[j] -= Base(k) * z[k] * x[j-k]; z[j] /= Base(j); z[j] += x[j]; z[j] /= x[0]; } } /*! Muiltiple directions Taylor coefficient for op = LogOp. The C++ source code corresponding to this operation is \verbatim z = log(x) \endverbatim \copydetails forward_unary1_op_dir */ template inline void forward_log_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { z[m+ell] = Base(q) * x[m+ell]; for(size_t k = 1; k < q; k++) z[m+ell] -= Base(k) * z[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell]; z[m+ell] /= (Base(q) * x[0]); } } /*! Compute zero order forward mode Taylor coefficient for result of op = LogOp. The C++ source code corresponding to this operation is \verbatim z = log(x) \endverbatim \copydetails forward_unary1_op_0 */ template inline void forward_log_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; z[0] = log( x[0] ); } /*! Compute reverse mode partial derivatives for result of op = LogOp. The C++ source code corresponding to this operation is \verbatim z = log(x) \endverbatim \copydetails reverse_unary1_op */ template inline void reverse_log_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { size_t j, k; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to result const Base* z = taylor + i_z * cap_order; Base* pz = partial + i_z * nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; j = d; while(j) { // scale partial w.r.t z[j] pz[j] /= x[0]; px[0] -= pz[j] * z[j]; px[j] += pz[j]; // further scale partial w.r.t. z[j] pz[j] /= Base(j); for(k = 1; k < j; k++) { pz[k] -= pz[j] * Base(k) * x[j-k]; px[j-k] -= pz[j] * Base(k) * z[k]; } --j; } px[0] += pz[0] / x[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/define.hpp0000644000176200001440000004151214536067013017430 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DEFINE_INCLUDED # define CPPAD_DEFINE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /*! \file define.hpp Define processor symbols and macros that are used by CppAD. */ /*! \def CPPAD_OP_CODE_TYPE Is the type used to store enum OpCode values. If not the same as OpCode, then sizeof(CPPAD_OP_CODE_TYPE) <= sizeof( enum OpCode ) to conserve memory. This type must support \c std::numeric_limits, the \c <= operator, and conversion to \c size_t. Make sure that the type chosen returns true for is_pod in pod_vector.hpp. */ # define CPPAD_OP_CODE_TYPE unsigned char /*! \def CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION A version of the inline command that works with MC compiler. Microsoft Visual C++ version 9.0 generates a warning if a template function is declared as a friend (this was not a problem for version 7.0). The warning identifier is \verbatim warning C4396 \endverbatim and it contains the text \verbatim the inline specifier cannot be used when a friend declaration refers to a specialization of a function template \endverbatim This happens even if the function is not a specialization. This macro is defined as empty for Microsoft compilers. */ # ifdef _MSC_VER # define CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION # else # define CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION inline # endif /*! \def CPPAD_NULL This preprocessor symbol is used for a null pointer. If it is not yet defined, it is defined when cppad/local/define.hpp is included. */ # ifndef CPPAD_NULL # if CPPAD_HAS_NULLPTR # define CPPAD_NULL nullptr # else # define CPPAD_NULL 0 # endif # endif /*! \def CPPAD_FOLD_ASSIGNMENT_OPERATOR(Op) Declares automatic coercion for certain AD assignment operations. This macro assumes that the operator \verbatim left Op right \endverbatim is defined for the case where left and right have type AD. It uses this case to define the cases where left has type AD and right has type VecAD_reference, Base, or double. The argument right is const and call by reference. This macro converts the operands to AD and then uses the definition of the same operation for that case. */ # define CPPAD_FOLD_ASSIGNMENT_OPERATOR(Op) \ /* ----------------------------------------------------------------*/ \ template \ inline AD& operator Op \ (AD &left, double right) \ { return left Op AD(right); } \ \ template \ inline AD& operator Op \ (AD &left, const Base &right) \ { return left Op AD(right); } \ \ inline AD& operator Op \ (AD &left, const double &right) \ { return left Op AD(right); } \ \ template \ inline AD& operator Op \ (AD &left, const VecAD_reference &right) \ { return left Op right.ADBase(); } // ===================================================================== /*! \def CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op) Declares automatic coercion for certain binary operations with AD result. This macro assumes that the operator \verbatim left Op right \endverbatim is defined for the case where left and right and the result of the operation all have type AD. It uses this case to define the cases either left or right has type VecAD_reference or AD and the type of the other operand is one of the following: VecAD_reference, AD, Base, double. All of the arguments are const and call by reference. This macro converts the operands to AD and then uses the definition of the same operation for that case. */ # define CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op) \ /* ----------------------------------------------------------------*/ \ /* Operations with VecAD_reference and AD only*/ \ \ template \ inline AD operator Op \ (const AD &left, const VecAD_reference &right) \ { return left Op right.ADBase(); } \ \ template \ inline AD operator Op \ (const VecAD_reference &left, const VecAD_reference &right)\ { return left.ADBase() Op right.ADBase(); } \ \ template \ inline AD operator Op \ (const VecAD_reference &left, const AD &right) \ { return left.ADBase() Op right; } \ /* ----------------------------------------------------------------*/ \ /* Operations Base */ \ \ template \ inline AD operator Op \ (const Base &left, const AD &right) \ { return AD(left) Op right; } \ \ template \ inline AD operator Op \ (const Base &left, const VecAD_reference &right) \ { return AD(left) Op right.ADBase(); } \ \ template \ inline AD operator Op \ (const AD &left, const Base &right) \ { return left Op AD(right); } \ \ template \ inline AD operator Op \ (const VecAD_reference &left, const Base &right) \ { return left.ADBase() Op AD(right); } \ \ /* ----------------------------------------------------------------*/ \ /* Operations double */ \ \ template \ inline AD operator Op \ (const double &left, const AD &right) \ { return AD(left) Op right; } \ \ template \ inline AD operator Op \ (const double &left, const VecAD_reference &right) \ { return AD(left) Op right.ADBase(); } \ \ template \ inline AD operator Op \ (const AD &left, const double &right) \ { return left Op AD(right); } \ \ template \ inline AD operator Op \ (const VecAD_reference &left, const double &right) \ { return left.ADBase() Op AD(right); } \ /* ----------------------------------------------------------------*/ \ /* Special case to avoid ambuigity when Base is double */ \ \ inline AD operator Op \ (const double &left, const AD &right) \ { return AD(left) Op right; } \ \ inline AD operator Op \ (const double &left, const VecAD_reference &right) \ { return AD(left) Op right.ADBase(); } \ \ inline AD operator Op \ (const AD &left, const double &right) \ { return left Op AD(right); } \ \ inline AD operator Op \ (const VecAD_reference &left, const double &right) \ { return left.ADBase() Op AD(right); } // ======================================================================= /*! \def CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(Op) Declares automatic coercion for certain binary operations with bool result. This macro assumes that the operator \verbatim left Op right \endverbatim is defined for the case where left and right have type AD and the result has type bool. It uses this case to define the cases either left or right has type VecAD_reference or AD and the type of the other operand is one of the following: VecAD_reference, AD, Base, double. All of the arguments are const and call by reference. This macro converts the operands to AD and then uses the definition of the same operation for that case. */ # define CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(Op) \ /* ----------------------------------------------------------------*/ \ /* Operations with VecAD_reference and AD only*/ \ \ template \ inline bool operator Op \ (const AD &left, const VecAD_reference &right) \ { return left Op right.ADBase(); } \ \ template \ inline bool operator Op \ (const VecAD_reference &left, const VecAD_reference &right)\ { return left.ADBase() Op right.ADBase(); } \ \ template \ inline bool operator Op \ (const VecAD_reference &left, const AD &right) \ { return left.ADBase() Op right; } \ /* ----------------------------------------------------------------*/ \ /* Operations Base */ \ \ template \ inline bool operator Op \ (const Base &left, const AD &right) \ { return AD(left) Op right; } \ \ template \ inline bool operator Op \ (const Base &left, const VecAD_reference &right) \ { return AD(left) Op right.ADBase(); } \ \ template \ inline bool operator Op \ (const AD &left, const Base &right) \ { return left Op AD(right); } \ \ template \ inline bool operator Op \ (const VecAD_reference &left, const Base &right) \ { return left.ADBase() Op AD(right); } \ \ /* ----------------------------------------------------------------*/ \ /* Operations double */ \ \ template \ inline bool operator Op \ (const double &left, const AD &right) \ { return AD(left) Op right; } \ \ template \ inline bool operator Op \ (const double &left, const VecAD_reference &right) \ { return AD(left) Op right.ADBase(); } \ \ template \ inline bool operator Op \ (const AD &left, const double &right) \ { return left Op AD(right); } \ \ template \ inline bool operator Op \ (const VecAD_reference &left, const double &right) \ { return left.ADBase() Op AD(right); } \ /* ----------------------------------------------------------------*/ \ /* Special case to avoid ambuigity when Base is double */ \ \ inline bool operator Op \ (const double &left, const AD &right) \ { return AD(left) Op right; } \ \ inline bool operator Op \ (const double &left, const VecAD_reference &right) \ { return AD(left) Op right.ADBase(); } \ \ inline bool operator Op \ (const AD &left, const double &right) \ { return left Op AD(right); } \ \ inline bool operator Op \ (const VecAD_reference &left, const double &right) \ { return left.ADBase() Op AD(right); } # endif TMB/inst/include/cppad/local/config.h.in0000644000176200001440000000210414113627761017505 0ustar liggesusers/* cppad/local/config.h.in. Generated from configure.ac by autoheader. */ /* is CPPAD_TESTVECTOR = boost vector (overriden if _MSC_VER defined) */ #undef CPPAD_BOOSTVECTOR /* is CPPAD_TESTVECTOR == CppAD::vector */ #undef CPPAD_CPPADVECTOR /* does system support gettimeofday (overriden if _MSC_VER defined) */ #undef CPPAD_HAS_GETTIMEOFDAY /* is CPPAD_TESTVECTOR == std::vector */ #undef CPPAD_STDVECTOR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Version number of package */ #undef VERSION /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif TMB/inst/include/cppad/local/vec_ad.hpp0000644000176200001440000004752714536067013017433 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_VEC_AD_INCLUDED # define CPPAD_VEC_AD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin VecAD$$ $spell cppad.hpp CondExpGt grep Ld vp Lu wc op Ldp Ldv Taylor VecAD const Cpp $$ $index VecAD$$ $index vector, AD index$$ $index record, AD index$$ $index tape, AD index$$ $index index, AD record$$ $section AD Vectors that Record Index Operations$$ $head Syntax$$ $codei%VecAD<%Base%> %v%(%n%)%$$ $pre $$ $icode%v%.size()%$$ $pre $$ $icode%b% = %v%[%i%]%$$ $pre $$ $icode%r% = %v%[%x%]%$$ $head Purpose$$ If either $icode v$$ or $icode x$$ is a $cref/variable/glossary/Variable/$$, the indexing operation $codei% %r% = %v%[%x%] %$$ is recorded in the corresponding AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$ and transferred to the corresponding $cref ADFun$$ object $icode f$$. Such an index can change each time zero order $cref/f.Forward/Forward/$$ is used; i.e., $icode f$$ is evaluated with new value for the $cref/independent variables/glossary/Tape/Independent Variable/$$. Note that the value of $icode y$$ depends on the value of $icode x$$ in a discrete fashion and CppAD computes its partial derivative with respect to $icode x$$ as zero. $head Alternatives$$ If only the values in the vector, and not the indices, depend on the independent variables, the class $icode%Vector%< AD<%Base%> >%$$ is much more efficient for storing AD values where $icode Vector$$ is any $cref SimpleVector$$ template class, If only the indices, and not the values in the vector, depend on the independent variables, The $cref Discrete$$ functions are a much more efficient way to represent these vectors. $head VecAD::reference$$ $index VecAD::reference$$ $index reference, VecAD$$ The result $icode r$$ has type $codei% VecAD<%Base%>::reference %$$ which is very much like the $codei%AD<%Base%>%$$ type with some notable exceptions: $subhead Exceptions$$ $list number$$ The object $icode r$$ cannot be used with the $cref Value$$ function to compute the corresponding $icode Base$$ value. If $icode v$$ and $icode i$$ are not $cref/variables/glossary/Variable/$$ $codei% %b% = v[%i%] %$$ can be used to compute the corresponding $icode Base$$ value. $lnext The object $icode r$$ cannot be used with the $cref/computed assignments operators/Arithmetic/$$ $code +=$$, $code -=$$, $code *=$$, or $code /=$$. For example, the following syntax is not valid: $codei% %v%[%x%] += %z%; %$$ no matter what the types of $icode z$$. $lnext Assignment to $icode r$$ returns a $code void$$. For example, the following syntax is not valid: $codei% %z% = %v%[%x%] = %u%; %$$ no matter what the types of $icode z$$, and $icode u$$. $lnext The $cref CondExp$$ functions do not accept $codei%VecAD<%Base%>::reference%$$ arguments. For example, the following syntax is not valid: $codei% CondExpGt(%v%[%x%], %z%, %u%, %v%) %$$ no matter what the types of $icode z$$, $icode u$$, and $icode v$$. $lnext The $cref/Parameter and Variable/ParVar/$$ functions cannot be used with $codei%VecAD<%Base%>::reference%$$ arguments like $icode r$$, use the entire $codei%VecAD<%Base%>%$$ vector instead; i.e. $icode v$$. $lnext The vectors passed to $cref Independent$$ must have elements of type $codei%AD<%Base%>%$$; i.e., $cref VecAD$$ vectors cannot be passed to $code Independent$$. $lnext If one uses this type in a AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$, $cref/sparsity pattern/glossary/Sparsity Pattern/$$ calculations ($cref Sparse$$) are less efficient because the dependence of different elements of the vector cannot be separated. $lend $head Constructor$$ $subhead v$$ The syntax $codei% VecAD<%Base%> %v%(%n%) %$$ creates an $code VecAD$$ object $icode v$$ with $icode n$$ elements. The initial value of the elements of $icode v$$ is unspecified. $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ $head size$$ The syntax $codei% %v%.size() %$$ returns the number of elements in the vector $icode v$$; i.e., the value of $icode n$$ when it was constructed. $head size_t Indexing$$ We refer to the syntax $codei% %b% = %v%[%i%] %$$ as $code size_t$$ indexing of a $code VecAD$$ object. This indexing is only valid if the vector $icode v$$ is a $cref/parameter/ParVar/$$; i.e., it does not depend on the independent variables. $subhead i$$ The operand $icode i$$ has prototype $codei% size_t %i% %$$ It must be greater than or equal zero and less than $icode n$$; i.e., less than the number of elements in $icode v$$. $subhead b$$ The result $icode b$$ has prototype $codei% %Base% %b% %$$ and is a reference to the $th i$$ element in the vector $icode v$$. It can be used to change the element value; for example, $codei% %v%[%i%] = %c% %$$ is valid where $icode c$$ is a $icode Base$$ object. The reference $icode b$$ is no longer valid once the destructor for $icode v$$ is called; for example, when $icode v$$ falls out of scope. $head AD Indexing$$ We refer to the syntax $codei% %r% = %v%[%x%] %$$ as AD indexing of a $code VecAD$$ object. $subhead x$$ The argument $icode x$$ has prototype $codei% const AD<%Base%> &%x% %$$ The value of $icode x$$ must be greater than or equal zero and less than $icode n$$; i.e., less than the number of elements in $icode v$$. $subhead r$$ The result $icode r$$ has prototype $codei% VecAD<%Base%>::reference %r% %$$ The object $icode r$$ has an AD type and its operations are recorded as part of the same AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$ as for $codei%AD<%Base%>%$$ objects. It acts as a reference to the element with index $latex {\rm floor} (x)$$ in the vector $icode v$$ ($latex {\rm floor} (x)$$ is the greatest integer less than or equal $icode x$$). Because it is a reference, it can be used to change the element value; for example, $codei% %v%[%x%] = %z% %$$ is valid where $icode z$$ is an $codei%VecAD<%Base%>::reference%$$ object. As a reference, $icode r$$ is no longer valid once the destructor for $icode v$$ is called; for example, when $icode v$$ falls out of scope. $head Example$$ $children% example/vec_ad.cpp %$$ The file $cref vec_ad.cpp$$ contains an example and test using $code VecAD$$ vectors. It returns true if it succeeds and false otherwise. $head Speed and Memory$$ The $cref VecAD$$ vector type is inefficient because every time an element of a vector is accessed, a new CppAD $cref/variable/glossary/Variable/$$ is created on the tape using either the $code Ldp$$ or $code Ldv$$ operation (unless all of the elements of the vector are $cref/parameters/glossary/Parameter/$$). The effect of this can be seen by executing the following steps: $list number$$ In the file $code cppad/local/forward1sweep.h$$, change the definition of $code CPPAD_FORWARD1SWEEP_TRACE$$ to $codep # define CPPAD_FORWARD1SWEEP_TRACE 1 $$ $lnext In the $code Example$$ directory, execute the command $codep ./test_one.sh lu_vec_ad_ok.cpp lu_vec_ad.cpp -DNDEBUG > lu_vec_ad_ok.log $$ This will write a trace of all the forward tape operations, for the test case $cref lu_vec_ad_ok.cpp$$, to the file $code lu_vec_ad_ok.log$$. $lnext In the $code Example$$ directory execute the commands $codep grep "op=" lu_vec_ad_ok.log | wc -l grep "op=Ld[vp]" lu_vec_ad_ok.log | wc -l grep "op=St[vp][vp]" lu_vec_ad_ok.log | wc -l $$ The first command counts the number of operators in the tracing, the second counts the number of VecAD load operations, and the third counts the number of VecAD store operations. (For CppAD version 05-11-20 these counts were 956, 348, and 118 respectively.) $lend $end ------------------------------------------------------------------------ */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file vec_ad.hpp Defines the VecAD class. */ /*! \def CPPAD_VEC_AD_COMPUTED_ASSIGNMENT(op, name) Prints an error message if the correspinding computed assignment is used. THis macro is used to print an error message if any of the computed assignments are used with the VecAD_reference class. The argument \c op is one of the following: += , -= , *= , /=. The argument \c name, is a string literal with the name of the computed assignment \c op. */ # define CPPAD_VEC_AD_COMPUTED_ASSIGNMENT(op, name) \ VecAD_reference& operator op (const VecAD_reference &right) \ { CPPAD_ASSERT_KNOWN( \ false, \ "Cannot use a ADVec element on left side of" name \ ); \ return *this; \ } \ VecAD_reference& operator op (const AD &right) \ { CPPAD_ASSERT_KNOWN( \ false, \ "Cannot use a ADVec element on left side of" name \ ); \ return *this; \ } \ VecAD_reference& operator op (const Base &right) \ { CPPAD_ASSERT_KNOWN( \ false, \ "Cannot use a ADVec element on left side of" name \ ); \ return *this; \ } /*! Class used to hold a reference to an element of a VecAD object. \tparam Base Elements of this class act like an AD (in a restricted sense), in addition they track (on the tape) the index they correspond to. */ template class VecAD_reference { friend bool Parameter (const VecAD &vec); friend bool Variable (const VecAD &vec); friend class VecAD; friend class ADTape; private: /// pointer to vecad vector that this is a element of VecAD *vec_; /// index in vecad vector that this element corresponds to AD ind_; // index for this element public: /*! consructor \param vec value of vec_ \param ind value of ind_ */ VecAD_reference(VecAD *vec, const AD& ind) : vec_( vec ) , ind_(ind) { } // assignment operators inline void operator = (const VecAD_reference &right); void operator = (const AD &right); void operator = (const Base &right); void operator = (int right); // computed assignments CPPAD_VEC_AD_COMPUTED_ASSIGNMENT( += , " += " ) CPPAD_VEC_AD_COMPUTED_ASSIGNMENT( -= , " -= " ) CPPAD_VEC_AD_COMPUTED_ASSIGNMENT( *= , " *= " ) CPPAD_VEC_AD_COMPUTED_ASSIGNMENT( /= , " /= " ) /// Conversion from VecAD_reference to AD. /// puts the correspond vecad load instruction in the tape. AD ADBase(void) const { AD result; size_t i = static_cast( Integer(ind_) ); CPPAD_ASSERT_UNKNOWN( i < vec_->length_ ); // AD value corresponding to this element result.value_ = vec_->data_[i]; // this address will be recorded in tape and must be // zero for parameters CPPAD_ASSERT_UNKNOWN( Parameter(result) ); result.taddr_ = 0; // index corresponding to this element if( Variable(*vec_) ) { ADTape* tape = AD::tape_ptr(vec_->tape_id_); CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL ); CPPAD_ASSERT_UNKNOWN( vec_->offset_ > 0 ); size_t load_op_index = tape->Rec_.num_load_op_rec(); if( IdenticalPar(ind_) ) { CPPAD_ASSERT_UNKNOWN( NumRes(LdpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(LdpOp) == 3 ); // put operand addresses in tape tape->Rec_.PutArg( vec_->offset_, i, load_op_index ); // put operator in the tape, ind_ is a parameter result.taddr_ = tape->Rec_.PutLoadOp(LdpOp); // change result to variable for this load result.tape_id_ = tape->id_; } else { CPPAD_ASSERT_UNKNOWN( NumRes(LdvOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(LdvOp) == 3 ); addr_t ind_taddr; if( Parameter(ind_) ) { // kludge that should not be needed // if ind_ instead of i is used for index // in the tape ind_taddr = tape->RecordParOp( ind_.value_ ); } else ind_taddr = ind_.taddr_; CPPAD_ASSERT_UNKNOWN( ind_taddr > 0 ); // put operand addresses in tape // (value of third arugment does not matter) tape->Rec_.PutArg( vec_->offset_, ind_taddr, load_op_index ); // put operator in the tape, ind_ is a variable result.taddr_ = tape->Rec_.PutLoadOp(LdvOp); // change result to variable for this load result.tape_id_ = tape->id_; } } return result; } }; /*! Vector of AD objects that tracks indexing operations on the tape. */ template class VecAD { friend bool Parameter (const VecAD &vec); friend bool Variable (const VecAD &vec); friend class ADTape; friend class VecAD_reference; friend std::ostream& operator << (std::ostream &os, const VecAD &vec_); private: /// size of this VecAD vector const size_t length_; /// elements of this vector pod_vector data_; /// offset in cummulate vector corresponding to this object size_t offset_; /// tape id corresponding to the offset tape_id_t tape_id_; public: /// declare the user's view of this type here typedef VecAD_reference reference; /// default constructor /// initialize tape_id_ same as for default constructor; see default.hpp VecAD(void) : length_(0) , offset_(0) , tape_id_(0) { CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); } /// sizing constructor /// initialize tape_id_ same as for parameters; see ad_copy.hpp VecAD(size_t n) : length_(n) , offset_(0) , tape_id_(0) { if( length_ > 0 ) { size_t i; Base zero(0); data_.extend(length_); // Initialize data to zero so all have same value. // This uses less memory and avoids a valgrind error // during TapeRec::PutPar for(i = 0; i < length_; i++) data_[i] = zero; } CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); } /// destructor ~VecAD(void) { } /// number of elements in the vector size_t size(void) { return length_; } /// element access (not taped) /// /// \param i /// element index Base &operator[](size_t i) { CPPAD_ASSERT_KNOWN( Parameter(*this), "VecAD: cannot use size_t indexing because this" " VecAD vector is a variable." ); CPPAD_ASSERT_KNOWN( i < length_, "VecAD: element index is >= vector length" ); return data_[i]; } /*! delayed taped elemement access \param x element index \par This operation may convert this vector from a parameter to a variable */ VecAD_reference operator[](const AD &x) { CPPAD_ASSERT_KNOWN( 0 <= Integer(x), "VecAD: element index is less than zero" ); CPPAD_ASSERT_KNOWN( static_cast( Integer(x) ) < length_, "VecAD: element index is >= vector length" ); // if no need to track indexing operation, return now if( Parameter(*this) & Parameter(x) ) return VecAD_reference(this, x); CPPAD_ASSERT_KNOWN( Parameter(*this) | Parameter(x) | (tape_id_ == x.tape_id_), "VecAD: vector and index are variables for" " different tapes." ); if( Parameter(*this) ) { // must place a copy of vector in tape offset_ = AD::tape_ptr(x.tape_id_)->AddVec(length_, data_); // Advance pointer by one so starts at first component of this // vector; i.e., skip lenght at begining (so is always > 0) offset_++; // tape id corresponding to this offest tape_id_ = x.tape_id_; } return VecAD_reference(this, x); } }; /*! Taped setting of element to a value. \param y value that element is set to. */ template void VecAD_reference::operator=(const AD &y) { if( Parameter(y) ) { // fold into the Base type assignment *this = y.value_; return; } CPPAD_ASSERT_UNKNOWN( y.taddr_ > 0 ); CPPAD_ASSERT_KNOWN( Parameter(*vec_) | (vec_->tape_id_ == y.tape_id_), "VecAD assignment: vector and new element value are variables" "\nfor different tapes." ); ADTape* tape = AD::tape_ptr(y.tape_id_); CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL ); if( Parameter(*vec_) ) { // must place a copy of vector in tape vec_->offset_ = tape->AddVec(vec_->length_, vec_->data_); // advance offset to be start of vector plus one (vec_->offset_)++; // tape id corresponding to this offest vec_->tape_id_ = y.tape_id_; } CPPAD_ASSERT_UNKNOWN( Variable(*vec_) ); // index in vector for this element size_t i = static_cast( Integer(ind_) ); CPPAD_ASSERT_UNKNOWN( i < vec_->length_ ); // assign value for this element (as an AD object) vec_->data_[i] = y.value_; // record the setting of this array element CPPAD_ASSERT_UNKNOWN( vec_->offset_ > 0 ); if( Parameter(ind_) ) { CPPAD_ASSERT_UNKNOWN( NumArg(StpvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(StpvOp) == 0 ); // put operand addresses in tape tape->Rec_.PutArg(vec_->offset_, i, y.taddr_); // put operator in the tape, ind_ is parameter, y is variable tape->Rec_.PutOp(StpvOp); } else { CPPAD_ASSERT_UNKNOWN( NumArg(StvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(StvvOp) == 0 ); CPPAD_ASSERT_UNKNOWN( ind_.taddr_ > 0 ); // put operand addresses in tape tape->Rec_.PutArg(vec_->offset_, ind_.taddr_, y.taddr_); // put operator in the tape, ind_ is variable, y is variable tape->Rec_.PutOp(StvvOp); } } /*! Taped setting of element to a value. \param y value that element is set to. */ template void VecAD_reference::operator=(const Base &y) { size_t i = static_cast( Integer(ind_) ); CPPAD_ASSERT_UNKNOWN( i < vec_->length_ ); // assign value for this element vec_->data_[i] = y; // check if this ADVec object is a parameter if( Parameter(*vec_) ) return; ADTape* tape = AD::tape_ptr(vec_->tape_id_); CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL ); // put value of the parameter y in the tape addr_t p = tape->Rec_.PutPar(y); // record the setting of this array element CPPAD_ASSERT_UNKNOWN( vec_->offset_ > 0 ); if( Parameter(ind_) ) { CPPAD_ASSERT_UNKNOWN( NumArg(StppOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(StppOp) == 0 ); // put operand addresses in tape tape->Rec_.PutArg(vec_->offset_, i, p); // put operator in the tape, ind_ is parameter, y is parameter tape->Rec_.PutOp(StppOp); } else { CPPAD_ASSERT_UNKNOWN( NumArg(StvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( NumRes(StvpOp) == 0 ); CPPAD_ASSERT_UNKNOWN( ind_.taddr_ > 0 ); // put operand addresses in tape tape->Rec_.PutArg(vec_->offset_, ind_.taddr_, p); // put operator in the tape, ind_ is variable, y is parameter tape->Rec_.PutOp(StvpOp); } } /*! Taped setting of element to a value. \param y value that element is set to. \par this case gets folded into case where value is AD. */ template inline void VecAD_reference::operator= (const VecAD_reference &y) { *this = y.ADBase(); } /*! Taped setting of element to a value. \param y value that element is set to. \par this case gets folded into case where value is Base. */ template inline void VecAD_reference::operator=(int y) { *this = Base(y); } } // END_CPPAD_NAMESPACE // preprocessor symbols that are local to this file # undef CPPAD_VEC_AD_COMPUTED_ASSIGNMENT # endif TMB/inst/include/cppad/local/op_code.hpp0000644000176200001440000006331414536067013017612 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_OP_CODE_INCLUDED # define CPPAD_OP_CODE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include # include # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file op_code.hpp Defines the OpCode enum type and functions related to it. */ /*! Type used to distinguish different AD< \a Base > atomic operations. Each of the operators ends with the characters Op. Ignoring the Op at the end, the operators appear in alphabetical order. Binary operation where both operands have type AD< \a Base > use the following convention for thier endings: \verbatim Ending Left-Operand Right-Operand pvOp parameter variable vpOp variable parameter vvOp variable variable \endverbatim For example, AddpvOp represents the addition operator where the left operand is a parameter and the right operand is a variable. */ // alphabetical order is checked by bin/check_op_code.sh enum OpCode { AbsOp, // abs(variable) AcosOp, // asin(variable) AddpvOp, // parameter + variable AddvvOp, // variable + variable AsinOp, // asin(variable) AtanOp, // atan(variable) BeginOp, // used to mark the beginning of the tape CExpOp, // CondExpRel(left, right, trueCase, falseCase) // arg[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne // arg[1] & 1 = is left a variable // arg[1] & 2 = is right a variable // arg[1] & 4 = is trueCase a variable // arg[1] & 8 = is falseCase a variable // arg[2] = index correspoding to left // arg[3] = index correspoding to right // arg[4] = index correspoding to trueCase // arg[5] = index correspoding to falseCase CosOp, // cos(variable) CoshOp, // cosh(variable) CSkipOp, // Conditional skip // arg[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne // arg[1] & 1 = is left a variable // arg[1] & 2 = is right a variable // arg[2] = index correspoding to left // arg[3] = index correspoding to right // arg[4] = number of operations to skip if CExpOp comparision is true // arg[5] = number of operations to skip if CExpOp comparision is false // arg[6] -> arg[5+arg[4]] = skip operations if true // arg[6+arg[4]] -> arg[5+arg[4]+arg[5]] = skip operations if false // arg[6+arg[4]+arg[5]] = arg[4] + arg[5] CSumOp, // Cummulative summation // arg[0] = number of addition variables in summation // arg[1] = number of subtraction variables in summation // arg[2] = index of parameter that initializes summation // arg[3] -> arg[2+arg[0]] = index for positive variables // arg[3+arg[0]] -> arg[2+arg[0]+arg[1]] = index for minus variables // arg[3+arg[0]+arg[1]] = arg[0] + arg[1] DisOp, // discrete::eval(index, variable) DivpvOp, // parameter / variable DivvpOp, // variable / parameter DivvvOp, // variable / variable EndOp, // used to mark the end of the tape EqpvOp, // parameter == variable EqvvOp, // variable == variable ErfOp, // erf(variable) ExpOp, // exp(variable) InvOp, // independent variable LdpOp, // z[parameter] LdvOp, // z[variable] LepvOp, // parameter <= variable LevpOp, // variable <= parameter LevvOp, // variable <= variable LogOp, // log(variable) LtpvOp, // parameter < variable LtvpOp, // variable < parameter LtvvOp, // variable < variable MulpvOp, // parameter * variable MulvvOp, // variable * variable NepvOp, // parameter != variable NevvOp, // variable != variable ParOp, // parameter PowpvOp, // pow(parameter, variable) PowvpOp, // pow(variable, parameter) PowvvOp, // pow(variable, variable) PriOp, // PrintFor(text, parameter or variable, parameter or variable) SignOp, // sign(variable) SinOp, // sin(variable) SinhOp, // sinh(variable) SqrtOp, // sqrt(variable) StppOp, // z[parameter] = parameter StpvOp, // z[parameter] = variable StvpOp, // z[variable] = parameter StvvOp, // z[variable] = variable SubpvOp, // parameter - variable SubvpOp, // variable - parameter SubvvOp, // variable - variable TanOp, // tan(variable) TanhOp, // tan(variable) // user atomic operation codes UserOp, // start of a user atomic operaiton // arg[0] = index of the operation if atomic_base class // arg[1] = extra information passed trough by deprecated old atomic class // arg[2] = number of arguments to this atomic function // arg[3] = number of results for this atomic function UsrapOp, // this user atomic argument is a parameter UsravOp, // this user atomic argument is a variable UsrrpOp, // this user atomic result is a parameter UsrrvOp, // this user atomic result is a variable NumberOp }; // Note that bin/check_op_code.sh assumes the pattern '^\tNumberOp$' occurs // at the end of this list and only at the end of this list. /*! Number of arguments for a specified operator. \return Number of arguments corresponding to the specified operator. \param op Operator for which we are fetching the number of arugments. \par NumArgTable this table specifes the number of arguments stored for each occurance of the operator that is the i-th value in the OpCode enum type. For example, for the first three OpCode enum values we have \verbatim OpCode j NumArgTable[j] Meaning AbsOp 0 1 index of variable we are taking absolute value of AcosOp 1 1 index of variable we are taking cosine of AddpvOp 1 2 indices of parameter and variable we are adding \endverbatim Note that the meaning of the arguments depends on the operator. */ inline size_t NumArg( OpCode op) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; // agreement with OpCode is checked by bin/check_op_code.sh static const size_t NumArgTable[] = { 1, // AbsOp 1, // AcosOp 2, // AddpvOp 2, // AddvvOp 1, // AsinOp 1, // AtanOp 1, // BeginOp offset first real argument to have index 1 6, // CExpOp 1, // CosOp 1, // CoshOp 0, // CSkipOp (actually has a variable number of arguments, not zero) 0, // CSumOp (actually has a variable number of arguments, not zero) 2, // DisOp 2, // DivpvOp 2, // DivvpOp 2, // DivvvOp 0, // EndOp 2, // EqpvOp 2, // EqvvOp 3, // ErfOp 1, // ExpOp 0, // InvOp 3, // LdpOp 3, // LdvOp 2, // LepvOp 2, // LevpOp 2, // LevvOp 1, // LogOp 2, // LtpvOp 2, // LtvpOp 2, // LtvvOp 2, // MulpvOp 2, // MulvvOp 2, // NepvOp 2, // NevvOp 1, // ParOp 2, // PowpvOp 2, // PowvpOp 2, // PowvvOp 5, // PriOp 1, // SignOp 1, // SinOp 1, // SinhOp 1, // SqrtOp 3, // StppOp 3, // StpvOp 3, // StvpOp 3, // StvvOp 2, // SubpvOp 2, // SubvpOp 2, // SubvvOp 1, // TanOp 1, // TanhOp 4, // UserOp 1, // UsrapOp 1, // UsravOp 1, // UsrrpOp 0 // UsrrvOp }; # ifndef NDEBUG // only do these checks once to save time static bool first = true; if( first ) { CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) == sizeof(NumArgTable) / sizeof(NumArgTable[0]) ); CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) <= std::numeric_limits::max() ); first = false; } // do this check every time CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) ); # endif return NumArgTable[op]; } /*! Number of variables resulting from the specified operation. \param op Operator for which we are fecching the number of results. \par NumResTable table specifes the number of varibles that result for each occurance of the operator that is the i-th value in the OpCode enum type. For example, for the first three OpCode enum values we have \verbatim OpCode j NumResTable[j] Meaning AbsOp 0 1 variable that is the result of the absolute value AcosOp 1 2 acos(x) and sqrt(1-x*x) are required for this op AddpvOp 1 1 variable that is the result of the addition \endverbatim */ inline size_t NumRes(OpCode op) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; // agreement with OpCode is checked by bin/check_op_code.sh static const size_t NumResTable[] = { 1, // AbsOp 2, // AcosOp 1, // AddpvOp 1, // AddvvOp 2, // AsinOp 2, // AtanOp 1, // BeginOp offsets first variable to have index one (not zero) 1, // CExpOp 2, // CosOp 2, // CoshOp 0, // CSkipOp 1, // CSumOp 1, // DisOp 1, // DivpvOp 1, // DivvpOp 1, // DivvvOp 0, // EndOp 0, // EqpvOp 0, // EqvvOp 5, // ErfOp 1, // ExpOp 1, // InvOp 1, // LdpOp 1, // LdvOp 0, // LepvOp 0, // LevpOp 0, // LevvOp 1, // LogOp 0, // LtpvOp 0, // LtvpOp 0, // LtvvOp 1, // MulpvOp 1, // MulvvOp 0, // NepvOp 0, // NevvOp 1, // ParOp 3, // PowpvOp 3, // PowvpOp 3, // PowvvOp 0, // PriOp 1, // SignOp 2, // SinOp 2, // SinhOp 1, // SqrtOp 0, // StppOp 0, // StpvOp 0, // StvpOp 0, // StvvOp 1, // SubpvOp 1, // SubvpOp 1, // SubvvOp 2, // TanOp 2, // TanhOp 0, // UserOp 0, // UsrapOp 0, // UsravOp 0, // UsrrpOp 1, // UsrrvOp 0 // Last entry not used: avoids g++ 4.3.2 warn when pycppad builds }; // check ensuring conversion to size_t is as expected CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) == sizeof(NumResTable) / sizeof(NumResTable[0]) - 1 ); // this test ensures that all indices are within the table CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) ); return NumResTable[op]; } /*! Fetch the name for a specified operation. \return name of the specified operation. \param op Operator for which we are fetching the name */ inline const char* OpName(OpCode op) { // agreement with OpCode is checked by bin/check_op_code.sh static const char *OpNameTable[] = { "Abs" , "Acos" , "Addpv" , "Addvv" , "Asin" , "Atan" , "Begin" , "CExp" , "Cos" , "Cosh" , "CSkip" , "CSum" , "Dis" , "Divpv" , "Divvp" , "Divvv" , "End" , "Eqpv" , "Eqvv" , "Erf" , "Exp" , "Inv" , "Ldp" , "Ldv" , "Lepv" , "Levp" , "Levv" , "Log" , "Ltpv" , "Ltvp" , "Ltvv" , "Mulpv" , "Mulvv" , "Nepv" , "Nevv" , "Par" , "Powpv" , "Powvp" , "Powvv" , "Pri" , "Sign" , "Sin" , "Sinh" , "Sqrt" , "Stpp" , "Stpv" , "Stvp" , "Stvv" , "Subpv" , "Subvp" , "Subvv" , "Tan" , "Tanh" , "User" , "Usrap" , "Usrav" , "Usrrp" , "Usrrv" }; // check ensuring conversion to size_t is as expected CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) == sizeof(OpNameTable)/sizeof(OpNameTable[0]) ); // this test ensures that all indices are within the table CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) ); return OpNameTable[op]; } /*! Prints a single field corresponding to an operator. A specified leader is printed in front of the value and then the value is left justified in the following width character. \tparam Type is the type of the value we are printing. \param os is the stream that we are printing to. \param leader are characters printed before the value. \param value is the value being printed. \param width is the number of character to print the value in. If the value does not fit in the width, the value is replace by width '*' characters. */ template void printOpField( std::ostream &os , const char * leader , const Type &value , size_t width ) { std::ostringstream buffer; std::string str; // first print the leader os << leader; // print the value into an internal buffer buffer << std::setw(width) << value; str = buffer.str(); // length of the string size_t len = str.size(); if( len > width ) { size_t i; for(i = 0; i < width-1; i++) os << str[i]; os << "*"; return; } // count number of spaces at begining size_t nspace = 0; while(str[nspace] == ' ' && nspace < len) nspace++; // left justify the string size_t i = nspace; while( i < len ) os << str[i++]; i = width - len + nspace; while(i--) os << " "; } /*! Prints a single operator and its operands \tparam Base Is the base type for these AD< \a Base > operations. \param os is the output stream that the information is printed on. \param play Is the entire recording for the tape that this operator is in. \param i_op is the index for the operator corresponding to this operation. \param i_var is the index for the variable corresponding to the result of this operation (if NumRes(op) > 0). \param op The operator code (OpCode) for this operation. \param ind is the vector of argument indices for this operation (must have NumArg(op) elements). */ template void printOp( std::ostream& os , const player* play , size_t i_op , size_t i_var , OpCode op , const addr_t* ind ) { size_t i; CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "cannot print trace of AD operations in parallel mode" ); static const char *CompareOpName[] = { "Lt", "Le", "Eq", "Ge", "Gt", "Ne" }; // print operator printOpField(os, "o=", i_op, 5); if( NumRes(op) > 0 && op != BeginOp ) printOpField(os, "v=", i_var, 5); else printOpField(os, "v=", "", 5); if( op == CExpOp || op == CSkipOp ) { printOpField(os, "", OpName(op), 5); printOpField(os, "", CompareOpName[ ind[0] ], 3); } else printOpField(os, "", OpName(op), 8); // print other fields size_t ncol = 5; switch( op ) { case CSkipOp: /* ind[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne ind[1] & 1 = is left a variable ind[1] & 2 = is right a variable ind[2] = index correspoding to left ind[3] = index correspoding to right ind[4] = number of operations to skip if CExpOp comparision is true ind[5] = number of operations to skip if CExpOp comparision is false ind[6] -> ind[5+ind[4]] = skip operations if true ind[6+ind[4]] -> ind[5+ind[4]+ind[5]] = skip operations if false ind[6+ind[4]+ind[5]] = ind[4] + ind[5] */ CPPAD_ASSERT_UNKNOWN( ind[6+ind[4]+ind[5]] == ind[4]+ind[5] ); CPPAD_ASSERT_UNKNOWN(ind[1] != 0); if( ind[1] & 1 ) printOpField(os, " vl=", ind[2], ncol); else printOpField(os, " pl=", play->GetPar(ind[2]), ncol); if( ind[1] & 2 ) printOpField(os, " vr=", ind[3], ncol); else printOpField(os, " pr=", play->GetPar(ind[3]), ncol); if( size_t(ind[4]) < 3 ) { for(i = 0; i < size_t(ind[4]); i++) printOpField(os, " ot=", ind[6+i], ncol); } else { printOpField(os, "\n\tot=", ind[6+0], ncol); for(i = 1; i < size_t(ind[4]); i++) printOpField(os, " ot=", ind[6+i], ncol); } if( size_t(ind[5]) < 3 ) { for(i = 0; i < size_t(ind[5]); i++) printOpField(os, " of=", ind[6+ind[4]+i], ncol); } else { printOpField(os, "\n\tof=", ind[6+ind[4]+0], ncol); { for(i = 1; i < size_t(ind[5]); i++) printOpField(os, " of=", ind[6+ind[4]+i], ncol); } } break; case CSumOp: /* ind[0] = number of addition variables in summation ind[1] = number of subtraction variables in summation ind[2] = index of parameter that initializes summation ind[3], ... , ind[2+ind[0]] = index for positive variables ind[3+ind[0]], ..., ind[2+ind[0]+ind[1]] = negative variables ind[3+ind[0]+ind[1]] == ind[0] + ind[1] */ CPPAD_ASSERT_UNKNOWN( ind[3+ind[0]+ind[1]] == ind[0]+ind[1] ); printOpField(os, " pr=", play->GetPar(ind[2]), ncol); for(i = 0; i < size_t(ind[0]); i++) printOpField(os, " +v=", ind[3+i], ncol); for(i = 0; i < size_t(ind[1]); i++) printOpField(os, " -v=", ind[3+ind[0]+i], ncol); break; case LdpOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); printOpField(os, "off=", ind[0], ncol); printOpField(os, "idx=", ind[1], ncol); break; case LdvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); printOpField(os, "off=", ind[0], ncol); printOpField(os, " v=", ind[1], ncol); break; case StppOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); printOpField(os, "off=", ind[0], ncol); printOpField(os, "idx=", ind[1], ncol); printOpField(os, " pr=", play->GetPar(ind[2]), ncol); break; case StpvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); printOpField(os, "off=", ind[0], ncol); printOpField(os, "idx=", ind[1], ncol); printOpField(os, " vr=", ind[2], ncol); break; case StvpOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); printOpField(os, "off=", ind[0], ncol); printOpField(os, " vl=", ind[1], ncol); printOpField(os, " pr=", play->GetPar(ind[2]), ncol); break; case StvvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); printOpField(os, "off=", ind[0], ncol); printOpField(os, " vl=", ind[1], ncol); printOpField(os, " vr=", ind[2], ncol); break; case AddvvOp: case DivvvOp: case LevvOp: case LtvvOp: case EqvvOp: case NevvOp: case MulvvOp: case PowvvOp: case SubvvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); printOpField(os, " vl=", ind[0], ncol); printOpField(os, " vr=", ind[1], ncol); break; case AddpvOp: case LepvOp: case LtpvOp: case EqpvOp: case NepvOp: case SubpvOp: case MulpvOp: case PowpvOp: case DivpvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); printOpField(os, " pl=", play->GetPar(ind[0]), ncol); printOpField(os, " vr=", ind[1], ncol); break; case DivvpOp: case LevpOp: case LtvpOp: case PowvpOp: case SubvpOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); printOpField(os, " vl=", ind[0], ncol); printOpField(os, " pr=", play->GetPar(ind[1]), ncol); break; case AbsOp: case AcosOp: case AsinOp: case AtanOp: case CosOp: case CoshOp: case ExpOp: case LogOp: case SignOp: case SinOp: case SinhOp: case SqrtOp: case UsravOp: case TanOp: case TanhOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); printOpField(os, " v=", ind[0], ncol); break; case ErfOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); // ind[1] points to the parameter 0 // ind[2] points to the parameter 2 / sqrt(pi) printOpField(os, " v=", ind[0], ncol); break; case ParOp: case UsrapOp: case UsrrpOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); printOpField(os, " p=", play->GetPar(ind[0]), ncol); break; case UserOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 ); { std::string name = atomic_base::class_name(ind[0]); printOpField(os, " f=", name.c_str(), ncol); printOpField(os, " i=", ind[1], ncol); printOpField(os, " n=", ind[2], ncol); printOpField(os, " m=", ind[3], ncol); } break; case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); if( ind[0] & 1 ) printOpField(os, " v=", ind[1], ncol); else printOpField(os, " p=", play->GetPar(ind[1]), ncol); os << "before=\"" << play->GetTxt(ind[2]) << "\""; if( ind[0] & 2 ) printOpField(os, " v=", ind[3], ncol); else printOpField(os, " p=", play->GetPar(ind[3]), ncol); os << "after=\"" << play->GetTxt(ind[4]) << "\""; break; case BeginOp: // argument not used (created by independent) CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); break; case EndOp: case InvOp: case UsrrvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 ); break; case DisOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); { const char* name = discrete::name(ind[0]); printOpField(os, " f=", name, ncol); printOpField(os, " x=", ind[1], ncol); } break; case CExpOp: CPPAD_ASSERT_UNKNOWN(ind[1] != 0); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 ); if( ind[1] & 1 ) printOpField(os, " vl=", ind[2], ncol); else printOpField(os, " pl=", play->GetPar(ind[2]), ncol); if( ind[1] & 2 ) printOpField(os, " vr=", ind[3], ncol); else printOpField(os, " pr=", play->GetPar(ind[3]), ncol); if( ind[1] & 4 ) printOpField(os, " vt=", ind[4], ncol); else printOpField(os, " pt=", play->GetPar(ind[4]), ncol); if( ind[1] & 8 ) printOpField(os, " vf=", ind[5], ncol); else printOpField(os, " pf=", play->GetPar(ind[5]), ncol); break; default: CPPAD_ASSERT_UNKNOWN(0); } } /*! Prints the result values correspnding to an operator. \tparam Base Is the base type for these AD< \a Base > operations. \tparam Value Determines the type of the values that we are printing. \param os is the output stream that the information is printed on. \param nfz is the number of forward sweep calculated values of type Value that correspond to this operation (ignored if NumRes(op) == 0). \param fz points to the first forward calculated value that correspond to this operation (ignored if NumRes(op) == 0). \param nrz is the number of reverse sweep calculated values of type Value that correspond to this operation (ignored if NumRes(op) == 0). \param rz points to the first reverse calculated value that correspond to this operation (ignored if NumRes(op) == 0). */ template void printOpResult( std::ostream &os , size_t nfz , const Value *fz , size_t nrz , const Value *rz ) { size_t k; for(k = 0; k < nfz; k++) os << "| fz[" << k << "]=" << fz[k]; for(k = 0; k < nrz; k++) os << "| rz[" << k << "]=" << rz[k]; } /*! If NDEBUG is not defined, assert that arguments come before result. \param op Operator for which we are checking order. All the operators are checked except for those of the form UserOp or Usr..Op. \param result is the variable index for the result. \param arg is a vector of lenght NumArg(op) pointing to the arguments for this operation. */ inline void assert_arg_before_result( OpCode op, const addr_t* arg, size_t result ) { switch( op ) { // These cases are not included below case UserOp: case UsrapOp: case UsravOp: case UsrrpOp: case UsrrvOp: break; // ------------------------------------------------------------------ // 0 arguments case CSkipOp: case CSumOp: case EndOp: case InvOp: break; // ------------------------------------------------------------------ // 1 argument, but is not used case BeginOp: break; // 1 argument , 1 result case AbsOp: case ExpOp: case LogOp: case ParOp: case SignOp: case SqrtOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < result ); break; // 1 argument, 2 results case AcosOp: case AsinOp: case AtanOp: case CosOp: case CoshOp: case SinOp: case SinhOp: case TanOp: case TanhOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) + 1 < result ); break; // 1 argument, 5 results case ErfOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) + 4 < result ); break; // ------------------------------------------------------------------ // 2 arguments, no results case LepvOp: case LtpvOp: case EqpvOp: case NepvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result ); break; // case LevpOp: case LtvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= result ); break; // case LevvOp: case LtvvOp: case EqvvOp: case NevvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= result ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result ); break; // 2 arguments (both variables), 1 results case AddvvOp: case DivvvOp: case MulvvOp: case SubvvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < result ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < result ); break; // 2 arguments (first variables), 1 results case DivvpOp: case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < result ); break; // 2 arguments (second variables), 1 results case AddpvOp: case DisOp: case DivpvOp: case MulpvOp: case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < result ); break; // 2 arguments (both variables), 3 results case PowvvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) + 2 < result ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) + 2 < result ); break; // 2 arguments (first variable), 3 results case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) + 2 < result ); break; // 2 arguments (second variable), 3 results case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) + 2 < result ); break; // ------------------------------------------------------------------ // 3 arguments, none variables case LdpOp: case StppOp: break; // 3 arguments, second variable, 1 result case LdvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < result ); break; // 3 arguments, third variable, no result case StpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) <= result ); break; // 3 arguments, second variable, no result case StvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result ); break; // 3 arguments, second and third variable, no result case StvvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) <= result ); break; // ------------------------------------------------------------------ // 5 arguments, no result case PriOp: if( arg[0] & 1 ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result ); } if( arg[0] & 2 ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) <= result ); } break; // ------------------------------------------------------------------ // 6 arguments, 1 result case CExpOp: if( arg[1] & 1 ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < result ); } if( arg[1] & 2 ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < result ); } if( arg[1] & 4 ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < result ); } if( arg[1] & 8 ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < result ); } break; // ------------------------------------------------------------------ default: CPPAD_ASSERT_UNKNOWN(false); break; } return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/base_complex.hpp0000644000176200001440000003223514536067013020641 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_BASE_COMPLEX_INCLUDED # define CPPAD_BASE_COMPLEX_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include /* $begin base_complex.hpp$$ $spell endif eps abs_geq Rel Lt Le Eq Ge Gt imag gcc isnan cppad.hpp sqrt exp cos std const CppAD Op inline enum undef acos asin atan erf Cond namespace bool $$ $index complex, double Base$$ $index Base, double complex$$ $index double, complex Base$$ $section Enable use of AD where Base is std::complex$$ $children%example/complex_poly.cpp %$$ $head Example$$ The file $cref complex_poly.cpp$$ contains an example use of $code std::complex$$ type for a CppAD $icode Base$$ type. It returns true if it succeeds and false otherwise. $head Include Order$$ This file is included before $code $$ so it is necessary to define the error handler in addition to including $cref/base_require.hpp/base_require/Include Order/$$ $codep */ # include # include # include # include /* $$ $head CondExpOp$$ The type $code std::complex$$ does not supports the $code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators; see $cref/not ordered/base_cond_exp/CondExpTemplate/Not Ordered/$$. Hence its $code CondExpOp$$ function is defined by $codep */ namespace CppAD { inline std::complex CondExpOp( enum CppAD::CompareOp cop , const std::complex &left , const std::complex &right , const std::complex &trueCase , const std::complex &falseCase ) { CppAD::ErrorHandler::Call( true , __LINE__ , __FILE__ , "std::complex CondExpOp(...)", "Error: cannot use CondExp with a complex type" ); return std::complex(0); } } /* $$ $head CondExpRel$$ The $cref/CPPAD_COND_EXP_REL/base_cond_exp/CondExpRel/$$ macro invocation $codep */ namespace CppAD { CPPAD_COND_EXP_REL( std::complex ) } /* $$ used $code CondExpOp$$ above to define $codei%CondExp%Rel%$$ for $code std::complex$$ arguments and $icode%Rel%$$ equal to $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, and $code Gt$$. $head EqualOpSeq$$ Complex numbers do not carry operation sequence information. Thus they are equal in this sense if and only if there values are equal. $codep */ namespace CppAD { inline bool EqualOpSeq( const std::complex &x , const std::complex &y ) { return x == y; } } /* $$ $head Identical$$ Complex numbers do not carry operation sequence information. Thus they are all parameters so the identical functions just check values. $codep */ namespace CppAD { inline bool IdenticalPar(const std::complex &x) { return true; } inline bool IdenticalZero(const std::complex &x) { return (x == std::complex(0., 0.) ); } inline bool IdenticalOne(const std::complex &x) { return (x == std::complex(1., 0.) ); } inline bool IdenticalEqualPar( const std::complex &x, const std::complex &y) { return (x == y); } } /* $$ $head Ordered$$ Complex types do not support comparison operators, $codep */ # undef CPPAD_USER_MACRO # define CPPAD_USER_MACRO(Fun) \ inline bool Fun(const std::complex& x) \ { CppAD::ErrorHandler::Call( \ true , __LINE__ , __FILE__ , \ #Fun"(x)", \ "Error: cannot use " #Fun " with x complex " \ ); \ return false; \ } namespace CppAD { CPPAD_USER_MACRO(LessThanZero) CPPAD_USER_MACRO(LessThanOrZero) CPPAD_USER_MACRO(GreaterThanOrZero) CPPAD_USER_MACRO(GreaterThanZero) inline bool abs_geq( const std::complex& x , const std::complex& y ) { return std::abs(x) >= std::abs(y); } } /* $$ $head erf$$ Complex types do not support the error function (use CPPAD_USER_MACRO define above). $codep */ # if CPPAD_COMPILER_HAS_ERF namespace CppAD { CPPAD_USER_MACRO(erf) } # endif /* $$ $head Integer$$ The implementation of this function must agree with the CppAD user specifications for complex arguments to the $cref/Integer/Integer/x/Complex Types/$$ function: $codep */ namespace CppAD { inline int Integer(const std::complex &x) { return static_cast( x.real() ); } } /* $$ $head isnan$$ The gcc 4.1.1 complier defines the function $codei% int std::complex::isnan( std::complex %z% ) %$$ (which is not specified in the C++ 1998 standard ISO/IEC 14882). This causes an ambiguity between the function above and the CppAD $cref/isnan/nan/$$ template function. We avoid this ambiguity by defining a non-template version of this function in the CppAD namespace. $codep */ namespace CppAD { inline bool isnan(const std::complex& z) { return (z != z); } } /* $$ $head Valid Unary Math$$ The following macro invocations define the standard unary math functions that are valid with complex arguments and are required to use $code AD< std::complex >$$. $codep */ namespace CppAD { CPPAD_STANDARD_MATH_UNARY(std::complex, cos) CPPAD_STANDARD_MATH_UNARY(std::complex, cosh) CPPAD_STANDARD_MATH_UNARY(std::complex, exp) CPPAD_STANDARD_MATH_UNARY(std::complex, log) CPPAD_STANDARD_MATH_UNARY(std::complex, sin) CPPAD_STANDARD_MATH_UNARY(std::complex, sinh) CPPAD_STANDARD_MATH_UNARY(std::complex, sqrt) } /* $$ $head Invalid Unary Math$$ The following macro definition and invocations define the standard unary math functions that are invalid with complex arguments and are required to use $code AD< std::complex >$$. $codep */ # undef CPPAD_USER_MACRO # define CPPAD_USER_MACRO(Fun) \ inline std::complex Fun(const std::complex& x) \ { CppAD::ErrorHandler::Call( \ true , __LINE__ , __FILE__ , \ #Fun"(x)", \ "Error: cannot use " #Fun " with x complex " \ ); \ return std::complex(0); \ } namespace CppAD { CPPAD_USER_MACRO(abs) CPPAD_USER_MACRO(acos) CPPAD_USER_MACRO(asin) CPPAD_USER_MACRO(atan) CPPAD_USER_MACRO(sign) } /* $$ $head pow $$ The following defines a $code CppAD::pow$$ function that is required to use $code AD< std::complex >$$: $codep */ namespace CppAD { inline std::complex pow( const std::complex &x , const std::complex &y ) { return std::pow(x, y); } } /*$$ $head limits$$ The following defines the numeric limits functions $code epsilon$$, $code min$$, and $code max$$ for the type $code std::complex$$. It also defines the deprecated $code epsilon$$ function: $codep */ namespace CppAD { template <> class numeric_limits< std::complex > { public: // machine epsilon static std::complex epsilon(void) { double eps = std::numeric_limits::epsilon(); return std::complex(eps, 0.0); } // minimum positive normalized value static std::complex min(void) { double min = std::numeric_limits::min(); return std::complex(min, 0.0); } // maximum finite value static std::complex max(void) { double max = std::numeric_limits::max(); return std::complex(max, 0.0); } }; // deprecated machine epsilon template <> inline std::complex epsilon< std::complex > (void) { return numeric_limits< std::complex >::epsilon(); } } /* $$ $end */ # undef CPPAD_USER_MACRO_ONE # define CPPAD_USER_MACRO_ONE(Fun) \ inline bool Fun(const std::complex& x) \ { CppAD::ErrorHandler::Call( \ true , __LINE__ , __FILE__ , \ #Fun"(x)", \ "Error: cannot use " #Fun " with x complex " \ ); \ return false; \ } # undef CPPAD_USER_MACRO_TWO # define CPPAD_USER_MACRO_TWO(Fun) \ inline std::complex Fun(const std::complex& x) \ { CppAD::ErrorHandler::Call( \ true , __LINE__ , __FILE__ , \ #Fun"(x)", \ "Error: cannot use " #Fun " with x complex " \ ); \ return std::complex(0); \ } namespace CppAD { // CondExpOp ------------------------------------------------------ inline std::complex CondExpOp( enum CppAD::CompareOp cop , const std::complex &left , const std::complex &right , const std::complex &trueCase , const std::complex &falseCase ) { CppAD::ErrorHandler::Call( true , __LINE__ , __FILE__ , "std::complex CondExpOp(...)", "Error: cannot use CondExp with a complex type" ); return std::complex(0); } // CondExpRel -------------------------------------------------------- CPPAD_COND_EXP_REL( std::complex ) // EqualOpSeq ----------------------------------------------------- inline bool EqualOpSeq( const std::complex &x , const std::complex &y ) { return x == y; } // Identical ------------------------------------------------------ inline bool IdenticalPar(const std::complex &x) { return true; } inline bool IdenticalZero(const std::complex &x) { return (x == std::complex(0., 0.) ); } inline bool IdenticalOne(const std::complex &x) { return (x == std::complex(1., 0.) ); } inline bool IdenticalEqualPar( const std::complex &x, const std::complex &y) { return (x == y); } // Ordered -------------------------------------------------------- CPPAD_USER_MACRO_ONE(LessThanZero) CPPAD_USER_MACRO_ONE(LessThanOrZero) CPPAD_USER_MACRO_ONE(GreaterThanOrZero) CPPAD_USER_MACRO_ONE(GreaterThanZero) inline bool abs_geq( const std::complex& x , const std::complex& y ) { return std::abs(x) >= std::abs(y); } // Integer ------------------------------------------------------ inline int Integer(const std::complex &x) { return static_cast( x.real() ); } // isnan ------------------------------------------------------------- inline bool isnan(const std::complex& z) { return (z != z); } // Valid standard math functions -------------------------------- CPPAD_STANDARD_MATH_UNARY(std::complex, cos) CPPAD_STANDARD_MATH_UNARY(std::complex, cosh) CPPAD_STANDARD_MATH_UNARY(std::complex, exp) CPPAD_STANDARD_MATH_UNARY(std::complex, log) CPPAD_STANDARD_MATH_UNARY(std::complex, sin) CPPAD_STANDARD_MATH_UNARY(std::complex, sinh) CPPAD_STANDARD_MATH_UNARY(std::complex, sqrt) // Invalid standrd math functions ------------------------------- CPPAD_USER_MACRO_TWO(abs) CPPAD_USER_MACRO_TWO(acos) CPPAD_USER_MACRO_TWO(asin) CPPAD_USER_MACRO_TWO(atan) CPPAD_USER_MACRO_TWO(sign) // The pow function inline std::complex pow( const std::complex &x , const std::complex &y ) { return std::pow(x, y); } // numeric_limits ------------------------------------------------- template <> class numeric_limits< std::complex > { public: /// machine epsilon static std::complex epsilon(void) { float eps = std::numeric_limits::epsilon(); return std::complex(eps, 0.0); } /// minimum positive normalized value static std::complex min(void) { float min = std::numeric_limits::min(); return std::complex(min, 0.0); } /// maximum finite value static std::complex max(void) { float max = std::numeric_limits::max(); return std::complex(max, 0.0); } }; template <> inline std::complex epsilon< std::complex >(void) { return numeric_limits< std::complex >::epsilon(); } } // undefine macros only used by this file # undef CPPAD_USER_MACRO # undef CPPAD_USER_MACRO_ONE # undef CPPAD_USER_MACRO_TWO # endif TMB/inst/include/cppad/local/for_sparse_jac.hpp0000644000176200001440000004600214536067013021155 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FOR_SPARSE_JAC_INCLUDED # define CPPAD_FOR_SPARSE_JAC_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ForSparseJac$$ $spell std var Jacobian Jac const Bool proportional VecAD $$ $section Jacobian Sparsity Pattern: Forward Mode$$ $index ForSparseJac$$ $index forward, sparsity Jacobian$$ $index sparsity, forward Jacobian$$ $index pattern, forward Jacobian$$ $head Syntax$$ $icode%s% = %f%.ForSparseJac(%q%, %r%) %$$ $icode%s% = %f%.ForSparseJac(%q%, %r%, %transpose%)%$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. For a fixed $latex n \times q$$ matrix $latex R$$, the Jacobian of $latex F[ x + R * u ]$$ with respect to $latex u$$ at $latex u = 0$$ is $latex \[ S(x) = F^{(1)} ( x ) * R \] $$ Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$, $code ForSparseJac$$ returns a sparsity pattern for the $latex S(x)$$. $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$. After a call to $code ForSparseJac$$, the sparsity pattern for each of the variables in the operation sequence is held in $icode f$$ (for possible later use by $cref RevSparseHes$$). These sparsity patterns are stored with elements of type $code bool$$ or elements of type $code std::set$$ (see $cref/VectorSet/ForSparseJac/VectorSet/$$ below). $subhead size_forward_bool$$ After $code ForSparseJac$$, if $icode k$$ is a $code size_t$$ object, $codei% %k% = %f%.size_forward_bool() %$$ sets $icode k$$ to the amount of memory (in unsigned character units) used to store the sparsity pattern with elements of type $code bool$$ in the function object $icode f$$. If the sparsity patterns for the previous $code ForSparseJac$$ used elements of type $code bool$$, the return value for $code size_forward_bool$$ will be non-zero. Otherwise, its return value will be zero. This sparsity pattern is stored for use by $cref RevSparseHes$$ and when it is not longer needed, it can be deleted (and the corresponding memory freed) using $codei% %f%.size_forward_bool(0) %$$ After this call, $icode%f%.size_forward_bool()%$$ will return zero. $subhead size_forward_set$$ After $code ForSparseJac$$, if $icode k$$ is a $code size_t$$ object, $codei% %k% = %f%.size_forward_set() %$$ sets $icode s$$ to the total number of elements in all the sets corresponding to the sparsity pattern stored in the function object $icode f$$. If the sparsity patterns for this operation use elements of type $code bool$$, the return value for $code size_forward_set$$ will be zero. Otherwise, its return value will be non-zero (unless the entire sparsity pattern is false). This sparsity pattern is stored for use by $cref RevSparseHes$$ and when it is not longer needed, it can be deleted (and the corresponding memory freed) using $codei% %f%.size_forward_set(0) %$$ After this call, $icode%f%.size_forward_set()%$$ will return zero. $head x$$ the sparsity pattern is valid for all values of the independent variables in $latex x \in B^n$$ (even if it has $cref CondExp$$ or $cref VecAD$$ operations). $head q$$ The argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of columns in $latex R \in B^{n \times q}$$ and the Jacobian $latex S(x) \in B^{m \times q}$$. $head transpose$$ The argument $icode transpose$$ has prototype $codei% bool %transpose% %$$ The default value $code false$$ is used when $icode transpose$$ is not present. $head r$$ The argument $icode r$$ has prototype $codei% const %VectorSet%& %r% %$$ see $cref/VectorSet/ForSparseJac/VectorSet/$$ below. $subhead transpose false$$ If $icode r$$ has elements of type $code bool$$, its size is $latex n * q$$. If it has elements of type $code std::set$$, its size is $latex n$$ and all the set elements must be between zero and $icode%q%-1%$$ inclusive. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex R \in B^{n \times q}$$. $subhead transpose true$$ If $icode r$$ has elements of type $code bool$$, its size is $latex q * n$$. If it has elements of type $code std::set$$, its size is $latex q$$ and all the set elements must be between zero and $icode%n%-1%$$ inclusive. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex R^\R{T} \in B^{q \times n}$$. $head s$$ The return value $icode s$$ has prototype $codei% %VectorSet% %s% %$$ see $cref/VectorSet/ForSparseJac/VectorSet/$$ below. $subhead transpose false$$ If $icode s$$ has elements of type $code bool$$, its size is $latex m * q$$. If it has elements of type $code std::set$$, its size is $latex m$$ and all its set elements are between zero and $icode%q%-1%$$ inclusive. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex S(x) \in B^{m \times q}$$. $subhead transpose true$$ If $icode s$$ has elements of type $code bool$$, its size is $latex q * m$$. If it has elements of type $code std::set$$, its size is $latex q$$ and all its set elements are between zero and $icode%m%-1%$$ inclusive. It specifies a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the matrix $latex S(x)^\R{T} \in B^{q \times m}$$. $head VectorSet$$ The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $code bool$$ or $code std::set$$; see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion of the difference. $head Entire Sparsity Pattern$$ Suppose that $latex q = n$$ and $latex R$$ is the $latex n \times n$$ identity matrix. In this case, the corresponding value for $icode s$$ is a sparsity pattern for the Jacobian $latex S(x) = F^{(1)} ( x )$$. $head Example$$ $children% example/for_sparse_jac.cpp %$$ The file $cref for_sparse_jac.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file for_sparse_jac.hpp Forward mode Jacobian sparsity patterns. */ // --------------------------------------------------------------------------- /*! Calculate Jacobian vector of bools sparsity patterns using forward mode. The C++ source code corresponding to this operation is \verbatim s = f.ForSparseJac(q, r) \endverbatim \tparam Base is the base type for this recording. \tparam VectorSet is a simple vector class with elements of type \c bool. \param transpose are the sparsity patterns transposed. \param q is the number of columns in the matrix \f$ R \f$. \param r is a sparsity pattern for the matrix \f$ R \f$. \param s The input value of \a s must be a vector with size \c m*q where \c m is the number of dependent variables corresponding to the operation sequence stored in \a play. The input value of the components of \c s does not matter. On output, \a s is the sparsity pattern for the matrix \f[ S(x) = F^{(1)} (x) * R \f] where \f$ F \f$ is the function corresponding to the operation sequence and \a x is any argument value. \param total_num_var is the total number of variable in this recording. \param dep_taddr maps dependendent variable index to the corresponding variable in the tape. \param ind_taddr maps independent variable index to the corresponding variable in the tape. \param play is the recording that defines the function we are computing the sparsity pattern for. \param for_jac_sparsity the input value of \a for_jac_sparsity does not matter. On output, \a for_jac_sparsity.n_set() == \a total_num_var and \a for_jac_sparsity.end() == \a q. It contains the forward sparsity pattern for all of the variables on the tape (given the sparsity pattern for the independent variables is \f$ R \f$). */ template void ForSparseJacBool( bool transpose , size_t q , const VectorSet& r , VectorSet& s , size_t total_num_var , CppAD::vector& dep_taddr , CppAD::vector& ind_taddr , CppAD::player& play , sparse_pack& for_jac_sparsity ) { // temporary indices size_t i, j; // range and domain dimensions for F size_t m = dep_taddr.size(); size_t n = ind_taddr.size(); CPPAD_ASSERT_KNOWN( q > 0, "ForSparseJac: q is not greater than zero" ); CPPAD_ASSERT_KNOWN( size_t(r.size()) == n * q, "ForSparseJac: size of r is not equal to\n" "q times domain dimension for ADFun object." ); // allocate memory for the requested sparsity calculation result for_jac_sparsity.resize(total_num_var, q); // set values corresponding to independent variables for(i = 0; i < n; i++) { CPPAD_ASSERT_UNKNOWN( ind_taddr[i] < total_num_var ); // ind_taddr[i] is operator taddr for i-th independent variable CPPAD_ASSERT_UNKNOWN( play.GetOp( ind_taddr[i] ) == InvOp ); // set bits that are true if( transpose ) { for(j = 0; j < q; j++) if( r[ j * n + i ] ) for_jac_sparsity.add_element( ind_taddr[i], j); } else { for(j = 0; j < q; j++) if( r[ i * q + j ] ) for_jac_sparsity.add_element( ind_taddr[i], j); } } // evaluate the sparsity patterns ForJacSweep( n, total_num_var, &play, for_jac_sparsity ); // return values corresponding to dependent variables CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == m * q ); for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr[i] < total_num_var ); // extract the result from for_jac_sparsity if( transpose ) { for(j = 0; j < q; j++) s[ j * m + i ] = false; } else { for(j = 0; j < q; j++) s[ i * q + j ] = false; } CPPAD_ASSERT_UNKNOWN( for_jac_sparsity.end() == q ); for_jac_sparsity.begin( dep_taddr[i] ); j = for_jac_sparsity.next_element(); while( j < q ) { if( transpose ) s[j * m + i] = true; else s[i * q + j] = true; j = for_jac_sparsity.next_element(); } } } /*! Calculate Jacobian vector of sets sparsity patterns using forward mode. The C++ source code corresponding to this operation is \verbatim s = f.ForSparseJac(q, r) \endverbatim \tparam Base see \c SparseJacBool. \tparam VectorSet is a simple vector class with elements of type \c std::set. \param transpose see \c SparseJacBool. \param q see \c SparseJacBool. \param r see \c SparseJacBool. \param s see \c SparseJacBool. \param total_num_var see \c SparseJacBool. \param dep_taddr see \c SparseJacBool. \param ind_taddr see \c SparseJacBool. \param play see \c SparseJacBool. \param for_jac_sparsity see \c SparseJacBool. */ template void ForSparseJacSet( bool transpose , size_t q , const VectorSet& r , VectorSet& s , size_t total_num_var , CppAD::vector& dep_taddr , CppAD::vector& ind_taddr , CppAD::player& play , CPPAD_INTERNAL_SPARSE_SET& for_jac_sparsity ) { // temporary indices size_t i, j; std::set::const_iterator itr; // range and domain dimensions for F size_t m = dep_taddr.size(); size_t n = ind_taddr.size(); CPPAD_ASSERT_KNOWN( q > 0, "RevSparseJac: q is not greater than zero" ); CPPAD_ASSERT_KNOWN( size_t(r.size()) == n || transpose, "RevSparseJac: size of r is not equal to n and transpose is false." ); CPPAD_ASSERT_KNOWN( size_t(r.size()) == q || ! transpose, "RevSparseJac: size of r is not equal to q and transpose is true." ); // allocate memory for the requested sparsity calculation for_jac_sparsity.resize(total_num_var, q); // set values corresponding to independent variables if( transpose ) { for(i = 0; i < q; i++) { // add the elements that are present itr = r[i].begin(); while( itr != r[i].end() ) { j = *itr++; CPPAD_ASSERT_KNOWN( j < n, "ForSparseJac: transpose is true and element of the set\n" "r[j] has value greater than or equal n." ); CPPAD_ASSERT_UNKNOWN( ind_taddr[j] < total_num_var ); // operator for j-th independent variable CPPAD_ASSERT_UNKNOWN( play.GetOp( ind_taddr[j] ) == InvOp ); for_jac_sparsity.add_element( ind_taddr[j], i); } } } else { for(i = 0; i < n; i++) { CPPAD_ASSERT_UNKNOWN( ind_taddr[i] < total_num_var ); // ind_taddr[i] is operator taddr for i-th independent variable CPPAD_ASSERT_UNKNOWN( play.GetOp( ind_taddr[i] ) == InvOp ); // add the elements that are present itr = r[i].begin(); while( itr != r[i].end() ) { j = *itr++; CPPAD_ASSERT_KNOWN( j < q, "ForSparseJac: an element of the set r[i] " "has value greater than or equal q." ); for_jac_sparsity.add_element( ind_taddr[i], j); } } } // evaluate the sparsity patterns ForJacSweep( n, total_num_var, &play, for_jac_sparsity ); // return values corresponding to dependent variables CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == m || transpose ); CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q || ! transpose ); for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr[i] < total_num_var ); // extract results from for_jac_sparsity // and add corresponding elements to sets in s CPPAD_ASSERT_UNKNOWN( for_jac_sparsity.end() == q ); for_jac_sparsity.begin( dep_taddr[i] ); j = for_jac_sparsity.next_element(); while( j < q ) { if( transpose ) s[j].insert(i); else s[i].insert(j); j = for_jac_sparsity.next_element(); } } } // --------------------------------------------------------------------------- /*! Private helper function for ForSparseJac(q, r). All of the description in the public member function ForSparseJac(q, r) applies. \param set_type is a \c bool value. This argument is used to dispatch to the proper source code depending on the value of \c VectorSet::value_type. \param transpose See \c ForSparseJac(q, r). \param q See \c ForSparseJac(q, r). \param r See \c ForSparseJac(q, r). \param s is the return value for the corresponding call to \c ForSparseJac(q, r). */ template template void ADFun::ForSparseJacCase( bool set_type , bool transpose , size_t q , const VectorSet& r , VectorSet& s ) { size_t m = Range(); // check VectorSet is Simple Vector class with bool elements CheckSimpleVector(); // dimension size of result vector s.resize( m * q ); // store results in s and for_jac_sparse_pack_ ForSparseJacBool( transpose , q , r , s , num_var_tape_ , dep_taddr_ , ind_taddr_ , play_ , for_jac_sparse_pack_ ); } /*! Private helper function for \c ForSparseJac(q, r). All of the description in the public member function \c ForSparseJac(q, r) applies. \param set_type is a \c std::set object. This argument is used to dispatch to the proper source code depending on the value of \c VectorSet::value_type. \param transpose See \c ForSparseJac(q, r). \param q See \c ForSparseJac(q, r). \param r See \c ForSparseJac(q, r). \param s is the return value for the corresponding call to \c ForSparseJac(q, r). */ template template void ADFun::ForSparseJacCase( const std::set& set_type , bool transpose , size_t q , const VectorSet& r , VectorSet& s ) { size_t m = Range(); // check VectorSet is Simple Vector class with sets for elements CheckSimpleVector, VectorSet>( one_element_std_set(), two_element_std_set() ); // dimension size of result vector if( transpose ) s.resize(q); else s.resize( m ); // store results in r and for_jac_sparse_pack_ CppAD::ForSparseJacSet( transpose , q , r , s , num_var_tape_ , dep_taddr_ , ind_taddr_ , play_ , for_jac_sparse_set_ ); } // --------------------------------------------------------------------------- /*! User API for Jacobian sparsity patterns using forward mode. The C++ source code corresponding to this operation is \verbatim s = f.ForSparseJac(q, r) \endverbatim \tparam Base is the base type for this recording. \tparam VectorSet is a simple vector with elements of type \c bool or \c std::set. \param q is the number of columns in the matrix \f$ R \f$. \param r is a sparsity pattern for the matrix \f$ R \f$. \param transpose are sparsity patterns for \f$ R \f$ and \f$ S(x) \f$ transposed. \return The value of \c transpose is false (true), the return value is a sparsity pattern for \f$ S(x) \f$ (\f$ S(x)^T \f$) where \f[ S(x) = F^{(1)} (x) * R \f] where \f$ F \f$ is the function corresponding to the operation sequence and \a x is any argument value. If \c VectorSet::value_type is \c bool, the return value has size \f$ m * q \f$ (\f$ q * m \f$). where \c m is the number of dependent variables corresponding to the operation sequence stored in \c f. If \c VectorSet::value_type is \c std::set, the return value has size \f$ m \f$ ( \f$ q \f$ ) and with all its elements between zero and \f$ q - 1 \f$ ( \f$ m - 1 \f$). \par Side Effects If \c VectorSet::value_type is \c bool, the forward sparsity pattern for all of the variables on the tape is stored in \c for_jac_sparse_pack__. In this case \verbatim for_jac_sparse_pack_.n_set() == num_var_tape_ for_jac_sparse_pack_.end() == q for_jac_sparse_set_.n_set() == 0 for_jac_sparse_set_.end() == 0 \endverbatim \n \n If \c VectorSet::value_type is \c std::set, the forward sparsity pattern for all of the variables on the tape is stored in \c for_jac_sparse_set__. In this case \verbatim for_jac_sparse_set_.n_set() == num_var_tape_ for_jac_sparse_set_.end() == q for_jac_sparse_pack_.n_set() == 0 for_jac_sparse_pack_.end() == 0 \endverbatim */ template template VectorSet ADFun::ForSparseJac( size_t q , const VectorSet& r , bool transpose ) { VectorSet s; typedef typename VectorSet::value_type Set_type; // free all memory currently in sparsity patterns for_jac_sparse_pack_.resize(0, 0); for_jac_sparse_set_.resize(0, 0); ForSparseJacCase( Set_type() , transpose , q , r , s ); return s; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/rev_jac_sweep.hpp0000644000176200001440000005027314536067013021016 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_REV_JAC_SWEEP_INCLUDED # define CPPAD_REV_JAC_SWEEP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file rev_jac_sweep.hpp Compute Reverse mode Jacobian sparsity patterns. */ /*! \def CPPAD_REV_JAC_SWEEP_TRACE This value is either zero or one. Zero is the normal operational value. If it is one, a trace of every rev_jac_sweep computation is printed. */ # define CPPAD_REV_JAC_SWEEP_TRACE 0 /* \def CPPAD_ATOMIC_CALL This avoids warnings when NDEBUG is defined and user_ok is not used. If \c NDEBUG is defined, this resolves to \code user_atom->rev_sparse_jac \endcode otherwise, it respolves to \code user_ok = user_atom->rev_sparse_jac \endcode This maco is undefined at the end of this file to facillitate is use with a different definition in other files. */ # ifdef NDEBUG # define CPPAD_ATOMIC_CALL user_atom->rev_sparse_jac # else # define CPPAD_ATOMIC_CALL user_ok = user_atom->rev_sparse_jac # endif /*! Given the sparsity pattern for the dependent variables, RevJacSweep computes the sparsity pattern for all the independent variables. \tparam Base base type for the operator; i.e., this operation sequence was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param nz_compare Are the derivatives with respect to left and right of the expression below considered to be non-zero: \code CondExpRel(left, right, if_true, if_false) \endcode This is used by the optimizer to obtain the correct dependency relations. \param n is the number of independent variables on the tape. \param numvar is the total number of variables on the tape; i.e., \a play->num_var_rec(). This is also the number of rows in the entire sparsity pattern \a RevJac. \param play The information stored in \a play is a recording of the operations corresponding to a function \f[ F : {\bf R}^n \rightarrow {\bf R}^m \f] where \f$ n \f$ is the number of independent variables and \f$ m \f$ is the number of dependent variables. The object \a play is effectly constant. It is not declared const because while playing back the tape the object \a play holds information about the currentl location with in the tape and this changes during playback. \param var_sparsity For i = 0 , ... , \a numvar - 1, (all the variables on the tape) the forward Jacobian sparsity pattern for variable i corresponds to the set with index i in \a var_sparsity. \b \b \b Input: For i = 0 , ... , \a numvar - 1, the forward Jacobian sparsity pattern for variable i is an input if i corresponds to a dependent variable. Otherwise the sparsity patten is empty. \n \n \b Output: For j = 1 , ... , \a n, the sparsity pattern for the dependent variable with index (j-1) is given by the set with index index j in \a var_sparsity. */ template void RevJacSweep( bool nz_compare, size_t n, size_t numvar, player *play, Vector_set& var_sparsity ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; size_t i, j, k; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // check numvar argument CPPAD_ASSERT_UNKNOWN( numvar > 0 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar ); // upper limit (exclusive) for elements in the set size_t limit = var_sparsity.end(); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index of the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparsity; vecad_sparsity.resize(num_vecad_vec, limit); pod_vector vecad_ind; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set to proper index for this VecAD vecad_ind[j] = i; for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // invalid index // start of next VecAD j += length + 1; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // work space used by UserOp. typedef std::set size_set; size_set::iterator set_itr; // iterator for a standard set size_set::iterator set_end; // end of iterator sequence vector< size_set > set_r; // set sparsity pattern for the argument x vector< size_set > set_s; // set sparisty pattern for the result y // vector bool_r; // bool sparsity pattern for the argument x vector bool_s; // bool sparisty pattern for the result y // const size_t user_q = limit; // maximum element plus one size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // user's atomic op calculator bool user_bool = false; // use bool or set sparsity ? # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_end; // Initialize play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REV_JAC_SWEEP_TRACE Rcout << std::endl; CppAD::vectorBool z_value(limit); # endif bool more_operators = true; while(more_operators) { // next op play->reverse_next(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); more_operators = false; break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_csum(op, arg, i_op, i_var); reverse_sparse_jacobian_csum_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case CExpOp: reverse_sparse_jacobian_cond_op( nz_compare, i_var, arg, num_par, var_sparsity ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); // derivative is identically zero break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[0] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // ------------------------------------------------- case LdpOp: reverse_sparse_jacobian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case LdvOp: reverse_sparse_jacobian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); break; // ------------------------------------------------- case PowvpOp: reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); break; // ------------------------------------------------- case SignOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); // derivative is identically zero break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case StppOp: // sparsity cannot proagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0); break; // ------------------------------------------------- case StpvOp: reverse_sparse_jacobian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case StvpOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); break; // ------------------------------------------------- case StvvOp: reverse_sparse_jacobian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case UserOp: // start or end atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_end ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_bool = user_atom->sparsity() == atomic_base::bool_sparsity_enum; if( user_bool ) { if( bool_r.size() != user_m * user_q ) bool_r.resize( user_m * user_q ); if( bool_s.size() != user_n * user_q ) bool_s.resize( user_n * user_q ); for(i = 0; i < user_m; i++) for(j = 0; j < user_q; j++) bool_r[ i * user_q + j] = false; } else { if(set_r.size() != user_m ) set_r.resize(user_m); if(set_s.size() != user_n ) set_s.resize(user_n); for(i = 0; i < user_m; i++) set_r[i].clear(); } user_j = user_n; user_i = user_m; user_state = user_ret; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base.rev_sparse_jac: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_state = user_end; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_j; if( user_j == 0 ) user_state = user_start; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); --user_j; // It might be faster if we add set union to var_sparsity // where one of the sets is not in var_sparsity. if( user_bool ) { for(j = 0; j < user_q; j++) if( bool_s[ user_j * user_q + j ] ) var_sparsity.add_element(arg[0], j); } else { set_itr = set_s[user_j].begin(); set_end = set_s[user_j].end(); while( set_itr != set_end ) var_sparsity.add_element(arg[0], *set_itr++); } if( user_j == 0 ) user_state = user_start; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_i; if( user_i == 0 ) { // call users function for this operation user_atom->set_id(user_id); if( user_bool) CPPAD_ATOMIC_CALL( user_q, bool_r, bool_s ); else CPPAD_ATOMIC_CALL( user_q, set_r, set_s ); user_state = user_arg; } break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); --user_i; var_sparsity.begin(i_var); i = var_sparsity.next_element(); while( i < user_q ) { if( user_bool ) bool_r[ user_i * user_q + i ] = true; else set_r[user_i].insert(i); i = var_sparsity.next_element(); } if( user_i == 0 ) { // call users function for this operation user_atom->set_id(user_id); if( user_bool) CPPAD_ATOMIC_CALL( user_q, bool_r, bool_s ); else CPPAD_ATOMIC_CALL( user_q, set_r, set_s ); user_state = user_arg; } break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_REV_JAC_SWEEP_TRACE for(j = 0; j < limit; j++) z_value[j] = false; var_sparsity.begin(i_var); j = var_sparsity.next_element(); while( j < limit ) { z_value[j] = true; j = var_sparsity.next_element(); } printOp( Rcout, play, i_op, i_var, op, arg ); if( NumRes(op) > 0 && op != BeginOp ) printOpResult( Rcout, 0, (CppAD::vectorBool *) CPPAD_NULL, 1, &z_value ); Rcout << std::endl; } Rcout << std::endl; # else } # endif // values corresponding to BeginOp CPPAD_ASSERT_UNKNOWN( i_op == 0 ); CPPAD_ASSERT_UNKNOWN( i_var == 0 ); return; } } // END_CPPAD_NAMESPACE // preprocessor symbols that are local to this file # undef CPPAD_REV_JAC_SWEEP_TRACE # undef CPPAD_ATOMIC_CALL # endif TMB/inst/include/cppad/local/asin_op.hpp0000644000176200001440000001533614536067013017633 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ASIN_OP_INCLUDED # define CPPAD_ASIN_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file asin_op.hpp Forward and reverse mode calculations for z = asin(x). */ /*! Compute forward mode Taylor coefficient for result of op = AsinOp. The C++ source code corresponding to this operation is \verbatim z = asin(x) \endverbatim The auxillary result is \verbatim y = sqrt(1 - x * x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_asin_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; Base* b = z - cap_order; // called y in documentation size_t k; Base uj; if( p == 0 ) { z[0] = asin( x[0] ); uj = Base(1) - x[0] * x[0]; b[0] = sqrt( uj ); p++; } for(size_t j = p; j <= q; j++) { uj = Base(0); for(k = 0; k <= j; k++) uj -= x[k] * x[j-k]; b[j] = Base(0); z[j] = Base(0); for(k = 1; k < j; k++) { b[j] -= Base(k) * b[k] * b[j-k]; z[j] -= Base(k) * z[k] * b[j-k]; } b[j] /= Base(j); z[j] /= Base(j); // b[j] += uj / Base(2); z[j] += x[j]; // b[j] /= b[0]; z[j] /= b[0]; } } /*! Multiple directions forward mode Taylor coefficient for op = AsinOp. The C++ source code corresponding to this operation is \verbatim z = asin(x) \endverbatim The auxillary result is \verbatim y = sqrt(1 - x * x) \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_asin_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; Base* b = z - num_taylor_per_var; // called y in documentation size_t k, ell; size_t m = (q-1) * r + 1; for(ell = 0; ell < r; ell ++) { Base uq = - 2.0 * x[m + ell] * x[0]; for(k = 1; k < q; k++) uq -= x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell]; b[m+ell] = Base(0); z[m+ell] = Base(0); for(k = 1; k < q; k++) { b[m+ell] += Base(k) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell]; z[m+ell] += Base(k) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell]; } b[m+ell] = ( uq / Base(2) - b[m+ell] / Base(q) ) / b[0]; z[m+ell] = ( x[m+ell] - z[m+ell] / Base(q) ) / b[0]; } } /*! Compute zero order forward mode Taylor coefficient for result of op = AsinOp. The C++ source code corresponding to this operation is \verbatim z = asin(x) \endverbatim The auxillary result is \verbatim y = sqrt( 1 - x * x ) \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_asin_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; Base* b = z - cap_order; // called y in documentation z[0] = asin( x[0] ); b[0] = sqrt( Base(1) - x[0] * x[0] ); } /*! Compute reverse mode partial derivatives for result of op = AsinOp. The C++ source code corresponding to this operation is \verbatim z = asin(x) \endverbatim The auxillary result is \verbatim y = sqrt( 1 - x * x ) \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_asin_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* z = taylor + i_z * cap_order; Base* pz = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* b = z - cap_order; // called y in documentation Base* pb = pz - nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; // number of indices to access size_t j = d; size_t k; while(j) { // scale partials w.r.t b[j] by 1 / b[0] pb[j] /= b[0]; // scale partials w.r.t z[j] by 1 / b[0] pz[j] /= b[0]; // update partials w.r.t b^0 pb[0] -= pz[j] * z[j] + pb[j] * b[j]; // update partial w.r.t. x^0 px[0] -= pb[j] * x[j]; // update partial w.r.t. x^j px[j] += pz[j] - pb[j] * x[0]; // further scale partial w.r.t. z[j] by 1 / j pz[j] /= Base(j); for(k = 1; k < j; k++) { // update partials w.r.t b^(j-k) pb[j-k] -= Base(k) * pz[j] * z[k] + pb[j] * b[k]; // update partials w.r.t. x^k px[k] -= pb[j] * x[j-k]; // update partials w.r.t. z^k pz[k] -= pz[j] * Base(k) * b[j-k]; } --j; } // j == 0 case px[0] += ( pz[0] - pb[0] * x[0]) / b[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/old_atomic.hpp0000644000176200001440000010224214536067013020306 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_OLD_ATOMIC_INCLUDED # define CPPAD_OLD_ATOMIC_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin old_atomic$$ $spell hes std Jacobian jac Tvector afun vx vy bool namespace CppAD const Taylor tx ty px py $$ $section User Defined Atomic AD Functions$$ $index CPPAD_USER_ATOMIC$$ $index atomic, user function$$ $index user, atomic function$$ $index operation, user atomic$$ $index function, user atomic$$ $head Syntax$$ Using $code CPPAD_USER_ATOMIC$$ has been deprecated. Use $cref atomic_base$$ instead. $subhead Define Function$$ $codei%CPPAD_USER_ATOMIC(%afun%, %Tvector%, %Base%, %forward%, %reverse%, %for_jac_sparse%, %rev_jac_sparse%, %rev_hes_sparse% ) %$$ $subhead Use Function$$ $icode%afun%(%id%, %ax%, %ay%) %$$ $subhead Callback Routines$$ $icode%ok% = %forward%(%id%, %k%, %n%, %m%, %vx%, %vy%, %tx%, %ty%) %$$ $icode%ok% = %reverse%(%id%, %k%, %n%, %m%, %tx%, %ty%, %px%, %py%) %$$ $icode%ok% = %for_jac_sparse%(%id%, %n%, %m%, %q%, %r%, %s%) %$$ $icode%ok% = %rev_jac_sparse%(%id%, %n%, %m%, %q%, %r%, %s%) %$$ $icode%ok% = %rev_hes_sparse%(%id%, %n%, %m%, %q%, %r%, %s%, %t%, %u%, %v%) %$$ $subhead Free Static Memory$$ $codei%user_atomic<%Base%>::clear()%$$ $head Purpose$$ In some cases, the user knows how to compute the derivative of a function $latex \[ y = f(x) \; {\rm where} \; f : B^n \rightarrow B^m \] $$ more efficiently than by coding it using $codei%AD<%Base%>%$$ $cref/atomic/glossary/Operation/Atomic/$$ operations and letting CppAD do the rest. In this case, $code CPPAD_USER_ATOMIC$$ can be used add the user code for $latex f(x)$$, and its derivatives, to the set of $codei%AD<%Base%>%$$ atomic operations. $pre $$ Another possible purpose is to reduce the size of the tape; see $cref/use AD/old_atomic/Example/Use AD/$$ $head Partial Implementation$$ The routines $cref/forward/old_atomic/forward/$$, $cref/reverse/old_atomic/reverse/$$, $cref/for_jac_sparse/old_atomic/for_jac_sparse/$$, $cref/rev_jac_sparse/old_atomic/rev_jac_sparse/$$, and $cref/rev_hes_sparse/old_atomic/rev_hes_sparse/$$, must be defined by the user. The $icode forward$$ the routine, for the case $icode%k% = 0%$$, must be implemented. Functions with the correct prototype, that just return $code false$$, can be used for the other cases (unless they are required by your calculations). For example, you need not implement $icode forward$$ for the case $icode%k% == 2%$$ until you require forward mode calculation of second derivatives. $head CPPAD_USER_ATOMIC$$ $index CPPAD_USER_ATOMIC$$ The macro $codei% CPPAD_USER_ATOMIC(%afun%, %Tvector%, %Base%, %forward%, %reverse%, %for_jac_sparse%, %rev_jac_sparse%, %rev_hes_sparse% ) %$$ defines the $codei%AD<%Base%>%$$ routine $icode afun$$. This macro can be placed within a namespace (not the $code CppAD$$ namespace) but must be outside of any routine. $subhead Tvector$$ The macro argument $icode Tvector$$ must be a $cref/simple vector template class/SimpleVector/$$. It determines the type of vectors used as arguments to the routine $icode afun$$. $subhead Base$$ The macro argument $icode Base$$ specifies the $cref/base type/base_require/$$ corresponding to $codei%AD<%Base>%$$ operation sequences. Calling the routine $icode afun$$ will add the operator defined by this macro to an $codei%AD<%Base>%$$ operation sequence. $head ok$$ For all routines documented below, the return value $icode ok$$ has prototype $codei% bool %ok% %$$ If it is $code true$$, the corresponding evaluation succeeded, otherwise it failed. $head id$$ For all routines documented below, the argument $icode id$$ has prototype $codei% size_t %id% %$$ Its value in all other calls is the same as in the corresponding call to $icode afun$$. It can be used to store and retrieve extra information about a specific call to $icode afun$$. $head k$$ For all routines documented below, the argument $icode k$$ has prototype $codei% size_t %k% %$$ The value $icode%k%$$ is the order of the Taylor coefficient that we are evaluating ($cref/forward/old_atomic/forward/$$) or taking the derivative of ($cref/reverse/old_atomic/reverse/$$). $head n$$ For all routines documented below, the argument $icode n$$ has prototype $codei% size_t %n% %$$ It is the size of the vector $icode ax$$ in the corresponding call to $icode%afun%(%id%, %ax%, %ay%)%$$; i.e., the dimension of the domain space for $latex y = f(x)$$. $head m$$ For all routines documented below, the argument $icode m$$ has prototype $codei% size_t %m% %$$ It is the size of the vector $icode ay$$ in the corresponding call to $icode%afun%(%id%, %ax%, %ay%)%$$; i.e., the dimension of the range space for $latex y = f(x)$$. $head tx$$ For all routines documented below, the argument $icode tx$$ has prototype $codei% const CppAD::vector<%Base%>& %tx% %$$ and $icode%tx%.size() >= (%k% + 1) * %n%$$. For $latex j = 0 , \ldots , n-1$$ and $latex \ell = 0 , \ldots , k$$, we use the Taylor coefficient notation $latex \[ \begin{array}{rcl} x_j^\ell & = & tx [ j * ( k + 1 ) + \ell ] \\ X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^k t^k \end{array} \] $$ If $icode%tx%.size() > (%k% + 1) * %n%$$, the other components of $icode tx$$ are not specified and should not be used. Note that superscripts represent an index for $latex x_j^\ell$$ and an exponent for $latex t^\ell$$. Also note that the Taylor coefficients for $latex X(t)$$ correspond to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way: $latex \[ x_j^\ell = \frac{1}{ \ell ! } X_j^{(\ell)} (0) \] $$ $head ty$$ In calls to $cref/forward/old_atomic/forward/$$, the argument $icode ty$$ has prototype $codei% CppAD::vector<%Base%>& %ty% %$$ while in calls to $cref/reverse/old_atomic/reverse/$$ it has prototype $codei% const CppAD::vector<%Base%>& %ty% %$$ For all calls, $icode%tx%.size() >= (%k% + 1) * %m%$$. For $latex i = 0 , \ldots , m-1$$ and $latex \ell = 0 , \ldots , k$$, we use the Taylor coefficient notation $latex \[ \begin{array}{rcl} y_i^\ell & = & ty [ i * ( k + 1 ) + \ell ] \\ Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^k t^k + o ( t^k ) \end{array} \] $$ where $latex o( t^k ) / t^k \rightarrow 0$$ as $latex t \rightarrow 0$$. If $icode%ty%.size() > (%k% + 1) * %m%$$, the other components of $icode ty$$ are not specified and should not be used. Note that superscripts represent an index for $latex y_j^\ell$$ and an exponent for $latex t^\ell$$. Also note that the Taylor coefficients for $latex Y(t)$$ correspond to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way: $latex \[ y_j^\ell = \frac{1}{ \ell ! } Y_j^{(\ell)} (0) \] $$ $subhead forward$$ In the case of $icode forward$$, for $latex i = 0 , \ldots , m-1$$, $latex ty[ i *( k + 1) + k ]$$ is an output and all the other components of $icode ty$$ are inputs. $subhead reverse$$ In the case of $icode reverse$$, all the components of $icode ty$$ are inputs. $head afun$$ The macro argument $icode afun$$, is the name of the AD function corresponding to this atomic operation (as it is used in the source code). CppAD uses the other functions, where the arguments are vectors with elements of type $icode Base$$, to implement the function $codei% %afun%(%id%, %ax%, %ay%) %$$ where the argument are vectors with elements of type $codei%AD<%Base%>%$$. $subhead ax$$ The $icode afun$$ argument $icode ax$$ has prototype $codei% const %Tvector%< AD<%Base%> >& %ax% %$$ It is the argument vector $latex x \in B^n$$ at which the $codei%AD<%Base%>%$$ version of $latex y = f(x)$$ is to be evaluated. The dimension of the domain space for $latex y = f (x)$$ is specified by $cref/n/old_atomic/n/$$ $codei%= %ax%.size()%$$, which must be greater than zero. $subhead ay$$ The $icode afun$$ result $icode ay$$ has prototype $codei% %Tvector%< AD<%Base%> >& %ay% %$$ The input values of its elements are not specified (must not matter). Upon return, it is the $codei%AD<%Base%>%$$ version of the result vector $latex y = f(x)$$. The dimension of the range space for $latex y = f (x)$$ is specified by $cref/m/old_atomic/m/$$ $codei%= %ay%.size()%$$, which must be greater than zero. $subhead Parallel Mode$$ $index parallel, old_atomic$$ $index old_atomic, parallel$$ The first call to $codei% %afun%(%id%, %ax%, %ay%) %$$ must not be in $cref/parallel/ta_in_parallel/$$ mode. In addition, the $cref/old_atomic clear/old_atomic/clear/$$ routine cannot be called while in parallel mode. $head forward$$ The macro argument $icode forward$$ is a user defined function $codei% %ok% = %forward%(%id%, %k%, %n%, %m%, %vx%, %vy%, %tx%, %ty%) %$$ that computes results during a $cref/forward/Forward/$$ mode sweep. For this call, we are given the Taylor coefficients in $icode tx$$ form order zero through $icode k$$, and the Taylor coefficients in $icode ty$$ with order less than $icode k$$. The $icode forward$$ routine computes the $icode k$$ order Taylor coefficients for $latex y$$ using the definition $latex Y(t) = f[ X(t) ]$$. For example, for $latex i = 0 , \ldots , m-1$$, $latex \[ \begin{array}{rcl} y_i^0 & = & Y(0) = f_i ( x^0 ) \\ y_i^1 & = & Y^{(1)} ( 0 ) = f_i^{(1)} ( x^0 ) X^{(1)} ( 0 ) = f_i^{(1)} ( x^0 ) x^1 \\ y_i^2 & = & \frac{1}{2 !} Y^{(2)} (0) \\ & = & \frac{1}{2} X^{(1)} (0)^\R{T} f_i^{(2)} ( x^0 ) X^{(1)} ( 0 ) + \frac{1}{2} f_i^{(1)} ( x^0 ) X^{(2)} ( 0 ) \\ & = & \frac{1}{2} (x^1)^\R{T} f_i^{(2)} ( x^0 ) x^1 + f_i^{(1)} ( x^0 ) x^2 \end{array} \] $$ Then, for $latex i = 0 , \ldots , m-1$$, it sets $latex \[ ty [ i * (k + 1) + k ] = y_i^k \] $$ The other components of $icode ty$$ must be left unchanged. $subhead Usage$$ This routine is used, with $icode%vx%.size() > 0%$$ and $icode%k% == 0%$$, by calls to $icode afun$$. It is used, with $icode%vx%.size() = 0%$$ and $icode k$$ equal to the order of the derivative begin computed, by calls to $cref/forward/forward_order/$$. $subhead vx$$ The $icode forward$$ argument $icode vx$$ has prototype $codei% const CppAD::vector& %vx% %$$ The case $icode%vx%.size() > 0%$$ occurs once for each call to $icode afun$$, during the call, and before any of the other callbacks corresponding to that call. Hence such a call can be used to cache information attached to the corresponding $icode id$$ (such as the elements of $icode vx$$). If $icode%vx%.size() > 0%$$ then $icode%k% == 0%$$, $icode%vx%.size() >= %n%$$, and for $latex j = 0 , \ldots , n-1$$, $icode%vx%[%j%]%$$ is true if and only if $icode%ax%[%j%]%$$ is a $cref/variable/glossary/Variable/$$. $pre $$ If $icode%vx%.size() == 0%$$, then $icode%vy%.size() == 0%$$ and neither of these vectors should be used. $subhead vy$$ The $icode forward$$ argument $icode vy$$ has prototype $codei% CppAD::vector& %vy% %$$ If $icode%vy%.size() == 0%$$, it should not be used. Otherwise, $icode%k% == 0%$$ and $icode%vy%.size() >= %m%$$. The input values of the elements of $icode vy$$ are not specified (must not matter). Upon return, for $latex j = 0 , \ldots , m-1$$, $icode%vy%[%i%]%$$ is true if and only if $icode%ay%[%j%]%$$ is a variable. (CppAD uses $icode vy$$ to reduce the necessary computations.) $head reverse$$ The macro argument $icode reverse$$ is a user defined function $codei% %ok% = %reverse%(%id%, %k%, %n%, %m%, %tx%, %ty%, %px%, %py%) %$$ that computes results during a $cref/reverse/Reverse/$$ mode sweep. The input value of the vectors $icode tx$$ and $icode ty$$ contain Taylor coefficient, up to order $icode k$$, for $latex X(t)$$ and $latex Y(t)$$ respectively. We use the $latex \{ x_j^\ell \}$$ and $latex \{ y_i^\ell \}$$ to denote these Taylor coefficients where the implicit range indices are $latex i = 0 , \ldots , m-1$$, $latex j = 0 , \ldots , n-1$$, $latex \ell = 0 , \ldots , k$$. Using the calculations done by $cref/forward/old_atomic/forward/$$, the Taylor coefficients $latex \{ y_i^\ell \}$$ are a function of the Taylor coefficients for $latex \{ x_j^\ell \}$$; i.e., given $latex y = f(x)$$ we define the function $latex F : B^{n \times (k+1)} \rightarrow B^{m \times (k+1)}$$ by $latex \[ y_i^\ell = F_i^\ell ( \{ x_j^\ell \} ) \] $$ We use $latex G : B^{m \times (k+1)} \rightarrow B$$ to denote an arbitrary scalar valued function of the Taylor coefficients for $latex Y(t)$$ and write $latex z = G( \{ y_i^\ell \} )$$. The $code reverse$$ routine is given the derivative of $latex z$$ with respect to $latex \{ y_i^\ell \}$$ and computes its derivative with respect to $latex \{ x_j^\ell \}$$. $subhead Usage$$ This routine is used, with $icode%k% + 1%$$ equal to the order of the derivative being calculated, by calls to $cref/reverse/reverse_any/$$. $subhead py$$ The $icode reverse$$ argument $icode py$$ has prototype $codei% const CppAD::vector<%Base%>& %py% %$$ and $icode%py%.size() >= (%k% + 1) * %m%$$. For $latex i = 0 , \ldots , m-1$$ and $latex \ell = 0 , \ldots , k$$, $latex \[ py[ i * (k + 1 ) + \ell ] = \partial G / \partial y_i^\ell \] $$ If $icode%py%.size() > (%k% + 1) * %m%$$, the other components of $icode py$$ are not specified and should not be used. $subhead px$$ We define the function $latex \[ H ( \{ x_j^\ell \} ) = G[ F( \{ x_j^\ell \} ) ] \] $$ The $icode reverse$$ argument $icode px$$ has prototype $codei% CppAD::vector<%Base%>& %px% %$$ and $icode%px%.size() >= (%k% + 1) * %n%$$. The input values of the elements of $icode px$$ are not specified (must not matter). Upon return, for $latex j = 0 , \ldots , n-1$$ and $latex p = 0 , \ldots , k$$, $latex \[ \begin{array}{rcl} px [ j * (k + 1) + p ] & = & \partial H / \partial x_j^p \\ & = & ( \partial G / \partial \{ y_i^\ell \} ) ( \partial \{ y_i^\ell \} / \partial x_j^p ) \\ & = & \sum_{i=0}^{m-1} \sum_{\ell=0}^k ( \partial G / \partial y_i^\ell ) ( \partial y_i^\ell / \partial x_j^p ) \\ & = & \sum_{i=0}^{m-1} \sum_{\ell=p}^k py[ i * (k + 1 ) + \ell ] ( \partial F_i^\ell / \partial x_j^p ) \end{array} \] $$ Note that we have used the fact that for $latex \ell < p$$, $latex \partial F_i^\ell / \partial x_j^p = 0$$. If $icode%px%.size() > (%k% + 1) * %n%$$, the other components of $icode px$$ are not specified and should not be used. $head for_jac_sparse$$ The macro argument $icode for_jac_sparse$$ is a user defined function $codei% %ok% = %for_jac_sparse%(%id%, %n%, %m%, %q%, %r%, %s%) %$$ that is used to compute results during a forward Jacobian sparsity sweep. For a fixed $latex n \times q$$ matrix $latex R$$, the Jacobian of $latex f( x + R * u)$$ with respect to $latex u \in B^q$$ is $latex \[ S(x) = f^{(1)} (x) * R \] $$ Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$, $icode for_jac_sparse$$ computes a sparsity pattern for $latex S(x)$$. $subhead Usage$$ This routine is used by calls to $cref ForSparseJac$$. $subhead q$$ The $icode for_jac_sparse$$ argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of columns in $latex R \in B^{n \times q}$$ and the Jacobian $latex S(x) \in B^{m \times q}$$. $subhead r$$ The $icode for_jac_sparse$$ argument $icode r$$ has prototype $codei% const CppAD::vector< std::set >& %r% %$$ and $icode%r%.size() >= %n%$$. For $latex j = 0 , \ldots , n-1$$, all the elements of $icode%r%[%j%]%$$ are between zero and $icode%q%-1%$$ inclusive. This specifies a sparsity pattern for the matrix $latex R$$. $subhead s$$ The $icode for_jac_sparse$$ return value $icode s$$ has prototype $codei% CppAD::vector< std::set >& %s% %$$ and $icode%s%.size() >= %m%%$$. The input values of its sets are not specified (must not matter). Upon return for $latex i = 0 , \ldots , m-1$$, all the elements of $icode%s%[%i%]%$$ are between zero and $icode%q%-1%$$ inclusive. This represents a sparsity pattern for the matrix $latex S(x)$$. $head rev_jac_sparse$$ The macro argument $icode rev_jac_sparse$$ is a user defined function $codei% %ok% = %rev_jac_sparse%(%id%, %n%, %m%, %q%, %r%, %s%) %$$ that is used to compute results during a reverse Jacobian sparsity sweep. For a fixed $latex q \times m$$ matrix $latex S$$, the Jacobian of $latex S * f( x )$$ with respect to $latex x \in B^n$$ is $latex \[ R(x) = S * f^{(1)} (x) \] $$ Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex S$$, $icode rev_jac_sparse$$ computes a sparsity pattern for $latex R(x)$$. $subhead Usage$$ This routine is used by calls to $cref RevSparseJac$$ and to $cref optimize$$. $subhead q$$ The $icode rev_jac_sparse$$ argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of rows in $latex S \in B^{q \times m}$$ and the Jacobian $latex R(x) \in B^{q \times n}$$. $subhead s$$ The $icode rev_jac_sparse$$ argument $icode s$$ has prototype $codei% const CppAD::vector< std::set >& %s% %$$ and $icode%s%.size() >= %m%$$. For $latex i = 0 , \ldots , m-1$$, all the elements of $icode%s%[%i%]%$$ are between zero and $icode%q%-1%$$ inclusive. This specifies a sparsity pattern for the matrix $latex S^\R{T}$$. $subhead r$$ The $icode rev_jac_sparse$$ return value $icode r$$ has prototype $codei% CppAD::vector< std::set >& %r% %$$ and $icode%r%.size() >= %n%$$. The input values of its sets are not specified (must not matter). Upon return for $latex j = 0 , \ldots , n-1$$, all the elements of $icode%r%[%j%]%$$ are between zero and $icode%q%-1%$$ inclusive. This represents a sparsity pattern for the matrix $latex R(x)^\R{T}$$. $head rev_hes_sparse$$ The macro argument $icode rev_hes_sparse$$ is a user defined function $codei% %ok% = %rev_hes_sparse%(%id%, %n%, %m%, %q%, %r%, %s%, %t%, %u%, %v%) %$$ There is an unspecified scalar valued function $latex g : B^m \rightarrow B$$. Given a sparsity pattern for $latex R$$ and information about the function $latex z = g(y)$$, this routine computes the sparsity pattern for $latex \[ V(x) = (g \circ f)^{(2)}( x ) R \] $$ $subhead Usage$$ This routine is used by calls to $cref RevSparseHes$$. $subhead q$$ The $icode rev_hes_sparse$$ argument $icode q$$ has prototype $codei% size_t %q% %$$ It specifies the number of columns in the sparsity patterns. $subhead r$$ The $icode rev_hes_sparse$$ argument $icode r$$ has prototype $codei% const CppAD::vector< std::set >& %r% %$$ and $icode%r%.size() >= %n%$$. For $latex j = 0 , \ldots , n-1$$, all the elements of $icode%r%[%j%]%$$ are between zero and $icode%q%-1%$$ inclusive. This specifies a sparsity pattern for the matrix $latex R \in B^{n \times q}$$. $subhead s$$ The $icode rev_hes_sparse$$ argument $icode s$$ has prototype $codei% const CppAD::vector& %s% %$$ and $icode%s%.size() >= %m%$$. This specifies a sparsity pattern for the matrix $latex S(x) = g^{(1)} (y) \in B^{1 \times m}$$. $subhead t$$ The $icode rev_hes_sparse$$ argument $icode t$$ has prototype $codei% CppAD::vector& %t% %$$ and $icode%t%.size() >= %n%$$. The input values of its elements are not specified (must not matter). Upon return it represents a sparsity pattern for the matrix $latex T(x) \in B^{1 \times n}$$ defined by $latex \[ T(x) = (g \circ f)^{(1)} (x) = S(x) * f^{(1)} (x) \] $$ $subhead u$$ The $icode rev_hes_sparse$$ argument $icode u$$ has prototype $codei% const CppAD::vector< std::set >& %u% %$$ and $icode%u%.size() >= %m%$$. For $latex i = 0 , \ldots , m-1$$, all the elements of $icode%u%[%i%]%$$ are between zero and $icode%q%-1%$$ inclusive. This specifies a sparsity pattern for the matrix $latex U(x) \in B^{m \times q}$$ defined by $latex \[ \begin{array}{rcl} U(x) & = & \partial_u \{ \partial_y g[ y + f^{(1)} (x) R u ] \}_{u=0} \\ & = & \partial_u \{ g^{(1)} [ y + f^{(1)} (x) R u ] \}_{u=0} \\ & = & g^{(2)} (y) f^{(1)} (x) R \end{array} \] $$ $subhead v$$ The $icode rev_hes_sparse$$ argument $icode v$$ has prototype $codei% CppAD::vector< std::set >& %v% %$$ and $icode%v%.size() >= %n%$$. The input values of its elements are not specified (must not matter). Upon return, for $latex j = 0, \ldots , n-1$$, all the elements of $icode%v%[%j%]%$$ are between zero and $icode%q%-1%$$ inclusive. This represents a sparsity pattern for the matrix $latex V(x) \in B^{n \times q}$$ defined by $latex \[ \begin{array}{rcl} V(x) & = & \partial_u [ \partial_x (g \circ f) ( x + R u ) ]_{u=0} \\ & = & \partial_u [ (g \circ f)^{(1)}( x + R u ) ]_{u=0} \\ & = & (g \circ f)^{(2)}( x ) R \\ & = & f^{(1)} (x)^\R{T} g^{(2)} ( y ) f^{(1)} (x) R + \sum_{i=1}^m [ g^{(1)} (y) ]_i \; f_i^{(2)} (x) R \\ & = & f^{(1)} (x)^\R{T} U(x) + \sum_{i=1}^m S(x)_i \; f_i^{(2)} (x) R \end{array} \] $$ $head clear$$ User atomic functions hold onto static work space in order to increase speed by avoiding system memory allocation calls. The function call $codei% user_atomic<%Base%>::clear() %$$ makes to work space $cref/available/ta_available/$$ to for other uses by the same thread. This should be called when you are done using the user atomic functions for a specific value of $icode Base$$. $subhead Restriction$$ The user atomic $code clear$$ routine cannot be called while in $cref/parallel/ta_in_parallel/$$ execution mode. $children% example/atomic/old_reciprocal.cpp% example/atomic/old_usead_1.cpp% example/atomic/old_usead_2.cpp% example/atomic/old_tan.cpp% example/atomic/old_mat_mul.cpp %$$ $head Example$$ $subhead Simple$$ The file $cref old_reciprocal.cpp$$ contains the simplest example and test of a user atomic operation. $subhead Use AD$$ The examples $cref old_usead_1.cpp$$ and $cref old_usead_2.cpp$$ use AD to compute the derivatives inside a user defined atomic function. This may have the advantage of reducing the size of the tape, because a repeated section of code would only be taped once. $subhead Tangent Function$$ The file $cref old_tan.cpp$$ contains an example and test implementation of the tangent function as a user atomic operation. $subhead Matrix Multiplication$$ The file $cref old_mat_mul.cpp$$ contains an example and test implementation of matrix multiplication a a user atomic operation. $end ------------------------------------------------------------------------------ */ # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file old_atomic.hpp user defined atomic operations. */ /*! \def CPPAD_USER_ATOMIC(afun, Tvector, forward, reverse, for_jac_sparse, rev_jac_sparse, rev_hes_sparse ) Defines the function afun(id, ax, ay) where \c id is \c ax and \c ay are vectors with AD elements. \par Tvector the Simple Vector template class for this function. \par Base the base type for the atomic operation. \par afun name of the CppAD defined function that corresponding to this operation. Note that \c afun, preceeded by a pound sign, is a version of \c afun with quotes arround it. \par forward name of the user defined function that computes corresponding results during forward mode. \par reverse name of the user defined function that computes corresponding results during reverse mode. \par for_jac_sparse name of the user defined routine that computes corresponding results during forward mode jacobian sparsity sweeps. \par rev_jac_sparse name of the user defined routine that computes corresponding results during reverse mode jacobian sparsity sweeps. \par rev_hes_sparse name of the user defined routine that computes corresponding results during reverse mode Hessian sparsity sweeps. \par memory allocation Note that old_atomic is used as a static object, so its objects do note get deallocated until the program terminates. */ # define CPPAD_USER_ATOMIC( \ afun , \ Tvector , \ Base , \ forward , \ reverse , \ for_jac_sparse , \ rev_jac_sparse , \ rev_hes_sparse \ ) \ inline void afun ( \ size_t id , \ const Tvector< CppAD::AD >& ax , \ Tvector< CppAD::AD >& ay \ ) \ { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; \ static CppAD::old_atomic fun( \ #afun , \ forward , \ reverse , \ for_jac_sparse , \ rev_jac_sparse , \ rev_hes_sparse \ ); \ fun(id, ax, ay); \ } /// link so that user_atomic::clear() still works template class user_atomic : public atomic_base { }; /*! Class that actually implements the afun(id, ax, ay) calls. A new old_atomic object is generated each time the user invokes the CPPAD_USER_ATOMIC macro; see static object in that macro. */ template class old_atomic : public atomic_base { public: /// disable old_atomic::clear(void) static void clear(void) { CPPAD_ASSERT_KNOWN( false, "Depreacted API uses user_atomic::clear()" ); } /// type for user routine that computes forward mode results typedef bool (*F) ( size_t id , size_t k , size_t n , size_t m , const vector& vx , vector& vy , const vector& tx , vector& ty ); /// type for user routine that computes reverse mode results typedef bool (*R) ( size_t id , size_t k , size_t n , size_t m , const vector& tx , const vector& ty , vector& px , const vector& py ); /// type for user routine that computes forward mode Jacobian sparsity typedef bool (*FJS) ( size_t id , size_t n , size_t m , size_t q , const vector< std::set >& r , vector< std::set >& s ); /// type for user routine that computes reverse mode Jacobian sparsity typedef bool (*RJS) ( size_t id , size_t n , size_t m , size_t q , vector< std::set >& r , const vector< std::set >& s ); /// type for user routine that computes reverse mode Hessian sparsity typedef bool (*RHS) ( size_t id , size_t n , size_t m , size_t q , const vector< std::set >& r , const vector& s , vector& t , const vector< std::set >& u , vector< std::set >& v ); private: /// id value corresponding to next virtual callback size_t id_; /// user's implementation of forward mode const F f_; /// user's implementation of reverse mode const R r_; /// user's implementation of forward jacobian sparsity calculations const FJS fjs_; /// user's implementation of reverse jacobian sparsity calculations const RJS rjs_; /// user's implementation of reverse Hessian sparsity calculations const RHS rhs_; public: /*! Constructor called for each invocation of CPPAD_USER_ATOMIC. Put this object in the list of all objects for this class and set the constant private data f_, r_, fjs_, rjs_, rhs_. \param afun is the user's name for the AD version of this atomic operation. \param f user routine that does forward mode calculations for this operation. \param r user routine that does reverse mode calculations for this operation. \param fjs user routine that does forward Jacobian sparsity calculations. \param rjs user routine that does reverse Jacobian sparsity calculations. \param rhs user routine that does reverse Hessian sparsity calculations. \par This constructor can not be used in parallel mode because atomic_base has this restriction. */ old_atomic(const char* afun, F f, R r, FJS fjs, RJS rjs, RHS rhs) : atomic_base(afun) // name = afun , f_(f) , r_(r) , fjs_(fjs) , rjs_(rjs) , rhs_(rhs) { this->option( atomic_base::set_sparsity_enum ); } /*! Implement the user call to afun(id, ax, ay). \tparam ADVector A simple vector class with elements of type AD. \param id extra information vector that is just passed through by CppAD, and possibly used by user's routines. \param ax is the argument vector for this call, ax.size() determines the number of arguments. \param ay is the result vector for this call, ay.size() determines the number of results. */ template void operator()(size_t id, const ADVector& ax, ADVector& ay) { // call atomic_base function object this->atomic_base::operator()(ax, ay, id); return; } /*! Store id for next virtual function callback \param id id value corresponding to next virtual callback */ virtual void set_id(size_t id) { id_ = id; } /*! Link from old_atomic to forward mode \copydetails atomic_base::forward */ virtual bool forward( size_t p , size_t q , const vector& vx , vector& vy , const vector& tx , vector& ty ) { CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 ); CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 ); size_t n = tx.size() / (q+1); size_t m = ty.size() / (q+1); size_t i, j, k, ell; vector x(n * (q+1)); vector y(m * (q+1)); vector empty; // old_atomic interface can only handel one order at a time // so must just throuh hoops to get multiple orders at one time. bool ok = true; for(k = p; k <= q; k++) { for(j = 0; j < n; j++) for(ell = 0; ell <= k; ell++) x[ j * (k+1) + ell ] = tx[ j * (q+1) + ell ]; for(i = 0; i < m; i++) for(ell = 0; ell < k; ell++) y[ i * (k+1) + ell ] = ty[ i * (q+1) + ell ]; if( k == 0 ) ok &= f_(id_, k, n, m, vx, vy, x, y); else ok &= f_(id_, k, n, m, empty, empty, x, y); for(i = 0; i < m; i++) ty[ i * (q+1) + k ] = y[ i * (k+1) + k]; } return ok; } /*! Link from old_atomic to reverse mode \copydetails atomic_base::reverse */ virtual bool reverse( size_t q , const vector& tx , const vector& ty , vector& px , const vector& py ) { CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 ); CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 ); size_t n = tx.size() / (q+1); size_t m = ty.size() / (q+1); bool ok = r_(id_, q, n, m, tx, ty, px, py); return ok; } /*! Link from forward Jacobian sparsity sweep to old_atomic \copydetails atomic_base::for_sparse_jac */ virtual bool for_sparse_jac( size_t q , const vector< std::set >& r , vector< std::set >& s ) { size_t n = r.size(); size_t m = s.size(); bool ok = fjs_(id_, n, m, q, r, s); return ok; } /*! Link from reverse Jacobian sparsity sweep to old_atomic. \copydetails atomic_base::rev_sparse_jac */ virtual bool rev_sparse_jac( size_t q , const vector< std::set >& rt , vector< std::set >& st ) { size_t n = st.size(); size_t m = rt.size(); bool ok = rjs_(id_, n, m, q, st, rt); return ok; } /*! Link from reverse Hessian sparsity sweep to old_atomic \copydetails atomic_base::rev_sparse_hes */ virtual bool rev_sparse_hes( const vector& vx, const vector& s , vector& t , size_t q , const vector< std::set >& r , const vector< std::set >& u , vector< std::set >& v ) { size_t m = u.size(); size_t n = v.size(); CPPAD_ASSERT_UNKNOWN( r.size() == n ); CPPAD_ASSERT_UNKNOWN( s.size() == m ); CPPAD_ASSERT_UNKNOWN( t.size() == n ); // // old interface used id instead of vx bool ok = rhs_(id_, n, m, q, r, s, t, u, v); return ok; } }; } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/jacobian.hpp0000644000176200001440000001325214536067013017744 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_JACOBIAN_INCLUDED # define CPPAD_JACOBIAN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Jacobian$$ $spell jac typename Taylor Jacobian DetLu const $$ $index Jacobian, driver$$ $index first, derivative$$ $index driver, Jacobian$$ $section Jacobian: Driver Routine$$ $head Syntax$$ $icode%jac% = %f%.Jacobian(%x%)%$$ $head Purpose$$ We use $latex F : B^n \rightarrow B^m$$ to denote the $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$. The syntax above sets $icode jac$$ to the Jacobian of $icode F$$ evaluated at $icode x$$; i.e., $latex \[ jac = F^{(1)} (x) \] $$ $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ Note that the $cref ADFun$$ object $icode f$$ is not $code const$$ (see $cref/Forward or Reverse/Jacobian/Forward or Reverse/$$ below). $head x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ (see $cref/Vector/Jacobian/Vector/$$ below) and its size must be equal to $icode n$$, the dimension of the $cref/domain/seq_property/Domain/$$ space for $icode f$$. It specifies that point at which to evaluate the Jacobian. $head jac$$ The result $icode jac$$ has prototype $codei% %Vector% %jac% %$$ (see $cref/Vector/Jacobian/Vector/$$ below) and its size is $latex m * n$$; i.e., the product of the $cref/domain/seq_property/Domain/$$ and $cref/range/seq_property/Range/$$ dimensions for $icode f$$. For $latex i = 0 , \ldots , m - 1 $$ and $latex j = 0 , \ldots , n - 1$$ $latex \[. jac[ i * n + j ] = \D{ F_i }{ x_j } ( x ) \] $$ $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type/SimpleVector/Elements of Specified Type/$$ $icode Base$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Forward or Reverse$$ This will use order zero Forward mode and either order one Forward or order one Reverse to compute the Jacobian (depending on which it estimates will require less work). After each call to $cref Forward$$, the object $icode f$$ contains the corresponding $cref/Taylor coefficients/glossary/Taylor Coefficient/$$. After a call to $code Jacobian$$, the zero order Taylor coefficients correspond to $icode%f%.Forward(0, %x%)%$$ and the other coefficients are unspecified. $head Example$$ $children% example/jacobian.cpp %$$ The routine $cref/Jacobian/jacobian.cpp/$$ is both an example and test. It returns $code true$$, if it succeeds and $code false$$ otherwise. $end ----------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template void JacobianFor(ADFun &f, const Vector &x, Vector &jac) { size_t i; size_t j; size_t n = f.Domain(); size_t m = f.Range(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector(); CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == f.Domain() ); CPPAD_ASSERT_UNKNOWN( size_t(jac.size()) == f.Range() * f.Domain() ); // argument and result for forward mode calculations Vector u(n); Vector v(m); // initialize all the components for(j = 0; j < n; j++) u[j] = Base(0); // loop through the different coordinate directions for(j = 0; j < n; j++) { // set u to the j-th coordinate direction u[j] = Base(1); // compute the partial of f w.r.t. this coordinate direction v = f.Forward(1, u); // reset u to vector of all zeros u[j] = Base(0); // return the result for(i = 0; i < m; i++) jac[ i * n + j ] = v[i]; } } template void JacobianRev(ADFun &f, const Vector &x, Vector &jac) { size_t i; size_t j; size_t n = f.Domain(); size_t m = f.Range(); CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == f.Domain() ); CPPAD_ASSERT_UNKNOWN( size_t(jac.size()) == f.Range() * f.Domain() ); // argument and result for reverse mode calculations Vector u(n); Vector v(m); // initialize all the components for(i = 0; i < m; i++) v[i] = Base(0); // loop through the different coordinate directions for(i = 0; i < m; i++) { if( f.Parameter(i) ) { // return zero for this component of f for(j = 0; j < n; j++) jac[ i * n + j ] = Base(0); } else { // set v to the i-th coordinate direction v[i] = Base(1); // compute the derivative of this component of f u = f.Reverse(1, v); // reset v to vector of all zeros v[i] = Base(0); // return the result for(j = 0; j < n; j++) jac[ i * n + j ] = u[j]; } } } template template Vector ADFun::Jacobian(const Vector &x) { size_t i; size_t n = Domain(); size_t m = Range(); CPPAD_ASSERT_KNOWN( size_t(x.size()) == n, "Jacobian: length of x not equal domain dimension for F" ); // point at which we are evaluating the Jacobian Forward(0, x); // work factor for forward mode size_t workForward = n; // work factor for reverse mode size_t workReverse = 0; for(i = 0; i < m; i++) { if( ! Parameter(i) ) ++workReverse; } // choose the method with the least work Vector jac( n * m ); if( workForward < workReverse ) JacobianFor(*this, x, jac); else JacobianRev(*this, x, jac); return jac; } } // END CppAD namespace # endif TMB/inst/include/cppad/local/forward0sweep.hpp0000644000176200001440000006032114536067013020765 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FORWARD0SWEEP_INCLUDED # define CPPAD_FORWARD0SWEEP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file forward0sweep.hpp Compute zero order forward mode Taylor coefficients. */ /* \def CPPAD_ATOMIC_CALL This avoids warnings when NDEBUG is defined and user_ok is not used. If NDEBUG is defined, this resolves to \code user_atom->forward \endcode otherwise, it respolves to \code user_ok = user_atom->forward \endcode This maco is undefined at the end of this file to facillitate is use with a different definition in other files. */ # ifdef NDEBUG # define CPPAD_ATOMIC_CALL user_atom->forward # else # define CPPAD_ATOMIC_CALL user_ok = user_atom->forward # endif /*! \def CPPAD_FORWARD0SWEEP_TRACE This value is either zero or one. Zero is the normal operational value. If it is one, a trace of every forward0sweep computation is printed. (Note that forward0sweep is not used if CPPAD_USE_FORWARD0SWEEP is zero). */ # if CPPAD_FORWARD0SWEEP_TRACE int do_trace; void traceforward0sweep(int trace) { do_trace = trace; } # define IF_TRACE if (do_trace) # else void traceforward0sweep(int trace) CSKIP( { // Default: Ignore }) # endif /*! Compute zero order forward mode Taylor coefficients. \tparam Base The type used during the forward mode computations; i.e., the corresponding recording of operations used the type AD. \param s_out Is the stream where output corresponding to PriOp operations will be written. \param print If print is false, suppress the output that is otherwise generated by the c PriOp instructions. \param n is the number of independent variables on the tape. \param numvar is the total number of variables on the tape. This is also equal to the number of rows in the matrix taylor; i.e., play->num_var_rec(). \param play The information stored in play is a recording of the operations corresponding to the function \f[ F : {\bf R}^n \rightarrow {\bf R}^m \f] where \f$ n \f$ is the number of independent variables and \f$ m \f$ is the number of dependent variables. \n \n The object play is effectly constant. The exception to this is that while palying back the tape the object play holds information about the current location with in the tape and this changes during palyback. \param J Is the number of columns in the coefficient matrix taylor. This must be greater than or equal one. \param taylor \n \b Input: For i = 1 , ... , n, taylor [i * J + 0] variable with index j on the tape (these are the independent variables). \n \n \b Output: For i = n + 1, ... , numvar - 1, taylor [i * J + 0] is the zero order Taylor coefficient for the variable with index i on the tape. \param cskip_op Is a vector with size play->num_op_rec(). The input value of the elements does not matter. Upon return, if cskip_op[i] is true, the operator index i does not affect any of the dependent variable (given the value of the independent variables). \param var_by_load_op Is a vector with size play->num_load_op_rec(). The input value of the elements does not matter. Upon return, it is the variable index corresponding the result for each load operator. In the case where the index is zero, the load operator results in a parameter (not a variable). Note that the is no variable with index zero on the tape. \param compare_change_count Is the count value for changing number and op_index during zero order foward mode. \param compare_change_number If compare_change_count is zero, this value is set to zero. Otherwise, the return value is the number of comparision operations that have a different result from when the information in play was recorded. \param compare_change_op_index If compare_change_count is zero, this value is set to zero. Otherwise it is the operator index (see forward_next) for the count-th comparision operation that has a different result from when the information in play was recorded. */ template void forward0sweep( std::ostream& s_out, bool print, size_t n, size_t numvar, player* play, size_t J, Base* taylor, bool* cskip_op, pod_vector& var_by_load_op, size_t compare_change_count, size_t& compare_change_number, size_t& compare_change_op_index ) { CPPAD_ASSERT_UNKNOWN( J >= 1 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); // use p, q, r so other forward sweeps can use code defined here size_t p = 0; size_t q = 0; size_t r = 1; /* */ // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; // operation argument indices const addr_t* arg = CPPAD_NULL; // initialize the comparision operator counter if( p == 0 ) { compare_change_number = 0; compare_change_op_index = 0; } // If this includes a zero calculation, initialize this information pod_vector isvar_by_ind; pod_vector index_by_ind; if( p == 0 ) { size_t i; // this includes order zero calculation, initialize vector indices size_t num = play->num_vec_ind_rec(); if( num > 0 ) { isvar_by_ind.extend(num); index_by_ind.extend(num); for(i = 0; i < num; i++) { index_by_ind[i] = play->GetVecInd(i); isvar_by_ind[i] = false; } } // includes zero order, so initialize conditional skip flags num = play->num_op_rec(); for(i = 0; i < num; i++) cskip_op[i] = false; } // work space used by UserOp. vector user_vx; // empty vecotor vector user_vy; // empty vecotor vector user_tx; // argument vector Taylor coefficients vector user_ty; // result vector Taylor coefficients size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end, user_trace } user_state = user_start; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // length of the text vector (used by CppAD assert macros) const size_t num_text = play->num_text_rec(); // pointer to the beginning of the text vector const char* text = CPPAD_NULL; if( num_text > 0 ) text = play->GetTxt(0); /* */ # if CPPAD_FORWARD0SWEEP_TRACE // variable indices for results vector // (done differently for order zero). vector user_iy; # endif // skip the BeginOp at the beginning of the recording play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD0SWEEP_TRACE IF_TRACE Rcout << std::endl; # endif bool more_operators = true; while(more_operators) { // this op play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var); // check if we are skipping this operation while( cskip_op[i_op] ) { if( op == CSumOp ) { // CSumOp has a variable number of arguments play->forward_csum(op, arg, i_op, i_var); } CPPAD_ASSERT_UNKNOWN( op != CSkipOp ); // if( op == CSkipOp ) // { // CSkip has a variable number of arguments // play->forward_cskip(op, arg, i_op, i_var); // } play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); } // action to take depends on the case switch( op ) { case AbsOp: forward_abs_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_addpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CExpOp: // Use the general case with d == 0 // (could create an optimzied verison for this case) forward_cond_op_0( i_var, arg, num_par, parameter, J, taylor ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op_0(i_var, arg[0], J, taylor); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_cskip_op_0( i_var, arg, num_par, parameter, J, taylor, cskip_op ); play->forward_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_csum_op( 0, 0, i_var, arg, num_par, parameter, J, taylor ); play->forward_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case DisOp: forward_dis_op(p, q, r, i_var, arg, J, taylor); break; // ------------------------------------------------- case DivvvOp: forward_divvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_divpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_divvp_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case EqpvOp: if( compare_change_count ) { forward_eqpv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case EqvvOp: if( compare_change_count ) { forward_eqvv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- # if CPPAD_COMPILER_HAS_ERF case ErfOp: CPPAD_ASSERT_UNKNOWN( CPPAD_COMPILER_HAS_ERF ); // 2DO: implement zero order version of this function forward_erf_op_0(i_var, arg, parameter, J, taylor); break; # endif // ------------------------------------------------- case ExpOp: forward_exp_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // --------------------------------------------------- case LdpOp: forward_load_p_op_0( play, i_var, arg, parameter, J, taylor, isvar_by_ind.data(), index_by_ind.data(), var_by_load_op.data() ); break; // ------------------------------------------------- case LdvOp: forward_load_v_op_0( play, i_var, arg, parameter, J, taylor, isvar_by_ind.data(), index_by_ind.data(), var_by_load_op.data() ); break; // ------------------------------------------------- case LepvOp: if( compare_change_count ) { forward_lepv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LevpOp: if( compare_change_count ) { forward_levp_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LevvOp: if( compare_change_count ) { forward_levv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LogOp: forward_log_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case LtpvOp: if( compare_change_count ) { forward_ltpv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LtvpOp: if( compare_change_count ) { forward_ltvp_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LtvvOp: if( compare_change_count ) { forward_ltvv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case MulvvOp: forward_mulvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_mulpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case NepvOp: if( compare_change_count ) { forward_nepv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case NevvOp: if( compare_change_count ) { forward_nevv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case ParOp: forward_par_op_0( i_var, arg, num_par, parameter, J, taylor ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_powvp_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_powpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PriOp: if( print ) forward_pri_0(s_out, arg, num_text, text, num_par, parameter, J, taylor ); break; // ------------------------------------------------- case SignOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sign_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case StppOp: forward_store_pp_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); break; // ------------------------------------------------- case StpvOp: forward_store_pv_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); break; // ------------------------------------------------- case StvpOp: forward_store_vp_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); break; // ------------------------------------------------- case StvvOp: forward_store_vv_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); break; // ------------------------------------------------- case SubvvOp: forward_subvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_subpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_subvp_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tan_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tanh_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_tx.size() != user_n) user_tx.resize(user_n); if(user_ty.size() != user_m) user_ty.resize(user_m); # if CPPAD_FORWARD0SWEEP_TRACE if( user_iy.size() != user_m ) user_iy.resize(user_m); # endif user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base.forward: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif # if CPPAD_FORWARD0SWEEP_TRACE user_state = user_trace; # else user_state = user_start; # endif } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); user_tx[user_j++] = parameter[ arg[0] ]; if( user_j == user_n ) { // call users function for this operation user_atom->set_id(user_id); CPPAD_ATOMIC_CALL(p, q, user_vx, user_vy, user_tx, user_ty ); user_state = user_ret; } break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); user_tx[user_j++] = taylor[ arg[0] * J + 0 ]; if( user_j == user_n ) { // call users function for this operation user_atom->set_id(user_id); CPPAD_ATOMIC_CALL(p, q, user_vx, user_vy, user_tx, user_ty ); user_state = user_ret; } break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); # if CPPAD_FORWARD0SWEEP_TRACE user_iy[user_i] = 0; # endif user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); # if CPPAD_FORWARD0SWEEP_TRACE user_iy[user_i] = i_var; # endif taylor[ i_var * J + 0 ] = user_ty[user_i++]; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(false); } # if CPPAD_FORWARD0SWEEP_TRACE size_t d = 0; if( user_state == user_trace ) { user_state = user_start; CPPAD_ASSERT_UNKNOWN( op == UserOp ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 ); for(size_t i = 0; i < user_m; i++) if( user_iy[i] > 0 ) { size_t i_tmp = (i_op + i) - user_m; IF_TRACE printOp( Rcout, play, i_tmp, user_iy[i], UsrrvOp, CPPAD_NULL ); Base* Z_tmp = taylor + user_iy[i] * J; IF_TRACE printOpResult( Rcout, d + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); IF_TRACE Rcout << std::endl; } } Base* Z_tmp = taylor + i_var * J; const addr_t* arg_tmp = arg; if( op == CSumOp ) arg_tmp = arg - arg[-1] - 4; if( op == CSkipOp ) arg_tmp = arg - arg[-1] - 7; if( op != UsrrvOp ) { IF_TRACE printOp( Rcout, play, i_op, i_var, op, arg_tmp ); if( NumRes(op) > 0 ) IF_TRACE printOpResult( Rcout, d + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); IF_TRACE Rcout << std::endl; } } IF_TRACE Rcout << std::endl; # else } # endif CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( i_var + 1 == play->num_var_rec() ); return; } } // END_CPPAD_NAMESPACE // preprocessor symbols that are local to this file # undef CPPAD_FORWARD0SWEEP_TRACE # undef CPPAD_ATOMIC_CALL # endif TMB/inst/include/cppad/local/ad_assign.hpp0000644000176200001440000000627014536067013020130 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_AD_ASSIGN_INCLUDED # define CPPAD_AD_ASSIGN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------ $begin ad_assign$$ $spell Vec const $$ $index assignment, AD$$ $index AD, assignment$$ $index assign, to AD$$ $index Base, assign to AD$$ $index VecAD, assign to AD$$ $section AD Assignment Operator$$ $head Syntax$$ $icode%y% = %x%$$ $head Purpose$$ Assigns the value in $icode x$$ to the object $icode y$$. In either case, $head x$$ The argument $icode x$$ has prototype $codei% const %Type% &%x% %$$ where $icode Type$$ is $codei%VecAD<%Base%>::reference%$$, $codei%AD<%Base%>%$$, $icode Base$$, or any type that has an implicit constructor of the form $icode%Base%(%x%)%$$. $head y$$ The target $icode y$$ has prototype $codei% AD<%Base%> %y% %$$ $head Example$$ $children% example/ad_assign.cpp %$$ The file $cref ad_assign.cpp$$ contain examples and tests of these operations. It test returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------ */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file ad_assign.hpp AD constructors and and copy operations. */ /*! \page AD_default_assign Use default assignment operator because they may be optimized better than the code below: \code template inline AD& AD::operator=(const AD &right) { value_ = right.value_; tape_id_ = right.tape_id_; taddr_ = right.taddr_; return *this; } \endcode */ /*! Assignment to Base type value. \tparam Base Base type for this AD object. \param b is the Base type value being assignment to this AD object. The tape identifier will be an invalid tape identifier, so this object is initially a parameter. */ template inline AD& AD::operator=(const Base &b) { value_ = b; tape_id_ = 0; // check that this is a parameter CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); return *this; } /*! Assignment to an ADVec element drops the vector information. \tparam Base Base type for this AD object. */ template inline AD& AD::operator=(const VecAD_reference &x) { return *this = x.ADBase(); } /*! Assignment from any other type, converts to Base type, and then uses assignment from Base type. \tparam Base Base type for this AD object. \tparam T is the the type that is being assigned to AD. There must be an assignment for Base from Type. \param t is the object that is being assigned to an AD object. */ template template inline AD& AD::operator=(const T &t) { return *this = Base(t); } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/player.hpp0000644000176200001440000005350214536067013017474 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_PLAYER_INCLUDED # define CPPAD_PLAYER_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file player.hpp File used to define the player class. */ struct tape_point{ OpCode op; const addr_t* op_arg; size_t op_index; size_t var_index; }; /*! Class used to store and play back an operation sequence recording. \tparam Base These were AD< \a Base > operations when recorded. Operations during playback are done using the type \a Base . */ template class player { // -------------- Variables that define the recording ----------------------- private: /// Number of variables in the recording. size_t num_var_rec_; /// number of vecad load opeations in the reconding size_t num_load_op_rec_; /// Number of VecAD vectors in the recording size_t num_vecad_vec_rec_; /// The operators in the recording. pod_vector op_rec_; /// The VecAD indices in the recording. pod_vector vecad_ind_rec_; /// The operation argument indices in the recording public: pod_vector op_arg_rec_; private: /// The parameters in the recording. /// Note that Base may not be plain old data, so use false in consructor. pod_vector par_rec_; /// Character strings ('\\0' terminated) in the recording. pod_vector text_rec_; // --------------- Functions used to create and maniplate a recording ------- public: /// Default constructor player(void) : num_var_rec_(0) , num_load_op_rec_(0) , op_rec_( std::numeric_limits::max() ) , vecad_ind_rec_( std::numeric_limits::max() ) , op_arg_rec_( std::numeric_limits::max() ) , par_rec_( std::numeric_limits::max() ) , text_rec_( std::numeric_limits::max() ) { } /// Destructor ~player(void) { } // =============================================================== /*! Moving an operation sequence from a recorder to a player \param rec the object that was used to record the operation sequence. After this operation, the state of the recording is no longer defined. For example, the \c pod_vector member variables in \c this have been swapped with \c rec . */ void get(recorder& rec) { size_t i; // just set size_t values num_var_rec_ = rec.num_var_rec_; num_load_op_rec_ = rec.num_load_op_rec_; // op_rec_ op_rec_.swap(rec.op_rec_); // vec_ind_rec_ vecad_ind_rec_.swap(rec.vecad_ind_rec_); // op_arg_rec_ op_arg_rec_.swap(rec.op_arg_rec_); // par_rec_ par_rec_.swap(rec.par_rec_); // text_rec_ text_rec_.swap(rec.text_rec_); // set the number of VecAD vectors num_vecad_vec_rec_ = 0; for(i = 0; i < vecad_ind_rec_.size(); i += vecad_ind_rec_[i] + 1) num_vecad_vec_rec_++; // vecad_ind_rec_ contains size of each VecAD followed by // the parameter indices used to iniialize it. CPPAD_ASSERT_UNKNOWN( i == vecad_ind_rec_.size() ); } // =============================================================== /*! Copying an operation sequence from one player to another \param play the object that contains the operatoion sequence to copy. */ void operator=(const player& play) { num_var_rec_ = play.num_var_rec_; num_load_op_rec_ = play.num_load_op_rec_; op_rec_ = play.op_rec_; num_vecad_vec_rec_ = play.num_vecad_vec_rec_; vecad_ind_rec_ = play.vecad_ind_rec_; op_arg_rec_ = play.op_arg_rec_; par_rec_ = play.par_rec_; text_rec_ = play.text_rec_; } // =============================================================== /// Erase all information in an operation sequence player. void Erase(void) { num_var_rec_ = 0; num_load_op_rec_ = 0; num_vecad_vec_rec_ = 0; op_rec_.erase(); vecad_ind_rec_.erase(); op_arg_rec_.erase(); par_rec_.erase(); text_rec_.erase(); } public: /*! \brief Old method of fetching an operator from the recording. \return the i-th operator in the recording. \param i the index of the operator in recording */ OpCode GetOp (size_t i) const { return OpCode(op_rec_[i]); } /*! \brief Fetch a VecAD index from the recording. \return the i-th VecAD index in the recording. \param i the index of the VecAD index in recording */ size_t GetVecInd (size_t i) const { return vecad_ind_rec_[i]; } /*! \brief Fetch a parameter from the recording. \return the i-th parameter in the recording. \param i the index of the parameter in recording */ Base GetPar(size_t i) const { return par_rec_[i]; } /*! \brief Fetch entire parameter vector from the recording. \return the entire parameter vector. */ const Base* GetPar(void) const { return par_rec_.data(); } /*! \brief Fetch a '\\0' terminated string from the recording. \return the beginning of the string. \param i the index where the string begins. */ const char *GetTxt(size_t i) const { CPPAD_ASSERT_UNKNOWN(i < text_rec_.size() ); return text_rec_.data() + i; } /// Fetch number of variables in the recording. size_t num_var_rec(void) const { return num_var_rec_; } /// Fetch number of vecad load operations size_t num_load_op_rec(void) const { return num_load_op_rec_; } /// Fetch number of operators in the recording. size_t num_op_rec(void) const { return op_rec_.size(); } /// Fetch number of VecAD indices in the recording. size_t num_vec_ind_rec(void) const { return vecad_ind_rec_.size(); } /// Fetch number of VecAD vectors in the recording size_t num_vecad_vec_rec(void) const { return num_vecad_vec_rec_; } /// Fetch number of argument indices in the recording. size_t num_op_arg_rec(void) const { return op_arg_rec_.size(); } /// Fetch number of parameters in the recording. size_t num_par_rec(void) const { return par_rec_.size(); } /// Fetch number of characters (representing strings) in the recording. size_t num_text_rec(void) const { return text_rec_.size(); } /// Fetch a rough measure of amount of memory used to store recording /// (just lengths, not capacities). size_t Memory(void) const { return op_rec_.size() * sizeof(OpCode) + op_arg_rec_.size() * sizeof(addr_t) + par_rec_.size() * sizeof(Base) + text_rec_.size() * sizeof(char) + vecad_ind_rec_.size() * sizeof(addr_t) ; } // ------------- Variables used for new methog of playing back a recording --- private: /// Current operator OpCode op_; /// Index in recording corresponding to current operator size_t op_index_; /// Current offset of the argument indices in op_arg_rec_ const addr_t* op_arg_; /// Index for primary (last) variable corresponding to current operator size_t var_index_; // ----------- Functions used in new method for palying back a recording --- public: /*! Start a play back of the recording during a forward sweep. Use repeated calls to forward_next to play back one operator at a time. \param op [out] The input value of \c op does not matter. Its output value is the first operator in the recording; i.e., BeginOp. \param op_arg [out] The input value of \c op_arg does not matter. Its output value is the beginning of the vector of argument indices for the first operation; i.e., 0 \param op_index [out] The input value of \c op_index does not matter. Its output value is the index of the next first operator in the recording; i.e., 0. \param var_index [out] The input value of \c var_index does not matter. Its output value is the index of the primary (last) result corresponding to the the first operator (which must be a BeginOp); i.e., 0. */ void forward_start( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { op = op_ = OpCode( op_rec_[0] ); op_arg = op_arg_ = op_arg_rec_.data(); op_index = op_index_ = 0; var_index = var_index_ = 0; CPPAD_ASSERT_UNKNOWN( op_ == BeginOp ); CPPAD_ASSERT_NARG_NRES(op_, 1, 1); return; } /*! Fetch the next operator during a forward sweep. Use forward_start to initialize to the first operator; i.e., the BeginOp at the beginning of the recording. We use the notation forward_routine to denote the set forward_start, forward_next, forward_csum, forward_cskip. \param op [in,out] The input value of \c op must be its output value from the previous call to a forward_routine. Its output value is the next operator in the recording. For speed, \c forward_next does not check for the special cases where op == CSumOp or op == CSkipOp. In these cases, the other return values from \c forward_next must be corrected by a call to \c forward_csum or \c forward_cskip respectively. \param op_arg [in,out] The input value of \c op_arg must be its output value form the previous call to a forward routine. Its output value is the beginning of the vector of argument indices for this operation. \param op_index [in,out] The input value of \c op_index must be its output value form the previous call to a forward routine. Its output value is the index of the next operator in the recording. Thus the ouput value following the previous call to forward_start is one. In addition, the output value increases by one with each call to forward_next. \param var_index [in,out] The input value of \c var_index must be its output value form the previous call to a forward routine. Its output value is the index of the primary (last) result corresponding to the operator op. */ void forward_next( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); // index for the next operator op_index = ++op_index_; // first argument for next operator op_arg = op_arg_ += NumArg(op_); // next operator op = op_ = OpCode( op_rec_[ op_index_ ] ); // index for last result for next operator var_index = var_index_ += NumRes(op); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); } /*! Correct \c forward_next return values when op == CSumOp. \param op [in] The input value of op must be the return value from the previous call to \c forward_next and must be \c CSumOp. It is not modified. \param op_arg [in,out] The input value of \c op_arg must be the return value from the previous call to \c forward_next. Its output value is the beginning of the vector of argument indices for the next operation. \param op_index [in] The input value of \c op_index does must be the return value from the previous call to \c forward_next. Its is not modified. \param var_index [in,out] The input value of \c var_index must be the return value from the previous call to \c forward_next. It is not modified. */ void forward_csum( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); CPPAD_ASSERT_UNKNOWN( op == CSumOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 ); CPPAD_ASSERT_UNKNOWN( op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ] ); /* The only thing that really needs fixing is op_arg_. Actual number of arugments for this operator is op_arg[0] + op_arg[1] + 4. We must change op_arg_ so that when you add NumArg(CSumOp) you get first argument for next operator in sequence. */ op_arg = op_arg_ += op_arg[0] + op_arg[1] + 4; CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); } /*! Correct \c forward_next return values when op == CSkipOp. \param op [in] The input value of op must be the return value from the previous call to \c forward_next and must be \c CSkipOp. It is not modified. \param op_arg [in,out] The input value of \c op_arg must be the return value from the previous call to \c forward_next. Its output value is the beginning of the vector of argument indices for the next operation. \param op_index [in] The input value of \c op_index does must be the return value from the previous call to \c forward_next. Its is not modified. \param var_index [in,out] The input value of \c var_index must be the return value from the previous call to \c forward_next. It is not modified. */ void forward_cskip( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); CPPAD_ASSERT_UNKNOWN( op == CSkipOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSkipOp) == 0 ); CPPAD_ASSERT_UNKNOWN( op_arg[4] + op_arg[5] == op_arg[ 6 + op_arg[4] + op_arg[5] ] ); /* The only thing that really needs fixing is op_arg_. Actual number of arugments for this operator is 7 + op_arg[4] + op_arg[5] We must change op_arg_ so that when you add NumArg(CSkipOp) you get first argument for next operator in sequence. */ op_arg = op_arg_ += 7 + op_arg[4] + op_arg[5]; CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); } /*! Start a play back of the recording during a reverse sweep. Use repeated calls to reverse_next to play back one operator at a time. \param op [out] The input value of \c op does not matter. Its output value is the last operator in the recording; i.e., EndOp. \param op_arg [out] The input value of \c op_arg does not matter. Its output value is the beginning of the vector of argument indices for the last operation; (there are no arguments for the last operation so \a op_arg is invalid). \param op_index [out[ The input value of \c op_index does not matter. Its output value is the index of the last operator in the recording. \param var_index [out] The input value of \c var_index does not matter. Its output value is the index of the primary (last) result corresponding to the the last operator (which must be a EndOp). (there are no results for the last operation so \a var_index is invalid). */ void reverse_start( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { op_arg = op_arg_ = op_arg_rec_.data() + op_arg_rec_.size(); op_index = op_index_ = op_rec_.size() - 1; var_index = var_index_ = num_var_rec_ - 1; op = op_ = OpCode( op_rec_[ op_index_ ] ); CPPAD_ASSERT_UNKNOWN( op_ == EndOp ); CPPAD_ASSERT_NARG_NRES(op, 0, 0); return; } /*! Fetch the next operator during a reverse sweep. Use reverse_start to initialize to reverse play back. The first call to reverse_next (after reverse_start) will give the last operator in the recording. We use the notation reverse_routine to denote the set reverse_start, reverse_next, reverse_csum, reverse_cskip. \param op [in,out] The input value of \c op must be its output value from the previous call to a reverse_routine. Its output value is the next operator in the recording (in reverse order). The last operator sets op equal to EndOp. \param op_arg [in,out] The input value of \c op_arg must be its output value from the previous call to a reverse_routine. Its output value is the beginning of the vector of argument indices for this operation. The last operator sets op_arg equal to the beginning of the argument indices for the entire recording. For speed, \c reverse_next does not check for the special cases op == CSumOp or op == CSkipOp. In these cases, the other return values from \c reverse_next must be corrected by a call to \c reverse_csum or \c reverse_cskip respectively. \param op_index [in,out] The input value of \c op_index must be its output value from the previous call to a reverse_routine. Its output value is the index of this operator in the recording. Thus the output value following the previous call to reverse_start is equal to the number of variables in the recording minus one. In addition, the output value decreases by one with each call to reverse_next. The last operator sets op_index equal to 0. \param var_index [in,out] The input value of \c var_index must be its output value from the previous call to a reverse_routine. Its output value is the index of the primary (last) result corresponding to the operator op. The last operator sets var_index equal to 0 (corresponding to BeginOp at beginning of operation sequence). */ void reverse_next( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); // index of the last result for the next operator CPPAD_ASSERT_UNKNOWN( var_index_ >= NumRes(op_) ); var_index = var_index_ -= NumRes(op_); // next operator CPPAD_ASSERT_UNKNOWN( op_index_ > 0 ); op_index = --op_index_; // index op = op_ = OpCode( op_rec_[ op_index_ ] ); // value // first argument for next operator op_arg = op_arg_ -= NumArg(op); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() ); } /*! Correct \c reverse_next return values when op == CSumOp. \param op [in] The input value of \c op must be the return value from the previous call to \c reverse_next and must be \c CSumOp. It is not modified. \param op_arg [in,out] The input value of \c op_arg must be the return value from the previous call to \c reverse_next. Its output value is the beginning of the vector of argument indices for this operation. \param op_index [in] The input value of \c op_index must be the return value from the previous call to \c reverse_next. It is not modified. \param var_index [in] The input value of \c var_index must be the return value from the previous call to \c reverse_next. It is not modified. */ void reverse_csum( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); CPPAD_ASSERT_UNKNOWN( op == CSumOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 ); /* The variables that need fixing are op_arg_ and op_arg. Currently, op_arg points to the last argument for the previous operator. */ // last argument for this csum operation --op_arg; // first argument for this csum operation op_arg = op_arg_ -= (op_arg[0] + 4); // now op_arg points to the first argument for this csum operator CPPAD_ASSERT_UNKNOWN( op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ] ); CPPAD_ASSERT_UNKNOWN( op_index_ < op_rec_.size() ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); } /*! Correct \c reverse_next return values when op == CSkipOp. \param op [int] The input value of \c op must be the return value from the previous call to \c reverse_next and must be \c CSkipOp. It is not modified. \param op_arg [in,out] The input value of \c op_arg must be the return value from the previous call to \c reverse_next. Its output value is the beginning of the vector of argument indices for this operation. \param op_index [in] The input value of \c op_index must be the return value from the previous call to \c reverse_next. It is not modified. \param var_index [in] The input value of \c var_index must be the return value from the previous call to \c reverse_next. It is not modified. */ void reverse_cskip( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); CPPAD_ASSERT_UNKNOWN( op == CSkipOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSkipOp) == 0 ); /* The variables that need fixing are op_arg_ and op_arg. Currently, op_arg points to the last arugment for the previous operator. */ // last argument for this cskip operation --op_arg; // first argument for this cskip operation op_arg = op_arg_ -= (op_arg[0] + 7); CPPAD_ASSERT_UNKNOWN( op_arg[4] + op_arg[5] == op_arg[ 6 + op_arg[4] + op_arg[5] ] ); CPPAD_ASSERT_UNKNOWN( op_index_ < op_rec_.size() ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); } }; } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/checkpoint.hpp0000644000176200001440000003615214536067013020331 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_CHECKPOINT_INCLUDED # define CPPAD_CHECKPOINT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file checkpoint.hpp defining checkpoint functions. */ /* $begin checkpoint$$ $spell cppad.hpp CppAD checkpoint checkpointing algo afun const $$ $section Checkpointing Functions$$ $index function, checkpoint$$ $index checkpoint, function$$ $head Syntax$$ $codei%checkpoint<%Base%> %afun%(%name%, %algo%, %ax%, %ay%) %afun%.option(%option_value%) %algo%(%ax%, %ay%) %afun%(%ax%, %ay%) checkpoint<%Base%>::clear()%$$ $head Purpose$$ You can reduce the size of the tape and memory required for AD by checkpointing functions of the form $latex y = f(x)$$ where $latex f : B^n \rightarrow B^m$$. $head Method$$ The $code checkpoint$$ class is derived from $code atomic_base$$ and makes this easy. It implements all the $code atomic_base$$ $cref/virtual functions/atomic_base/Virtual Functions/$$ and hence its source code $code cppad/local/checkpoint.hpp$$ provides an example implementation of $cref atomic_base$$. The difference is that $code checkpoint.hpp$$ uses AD instead of user provided derivatives. $head constructor$$ The constructor $codei% checkpoint<%Base%> %afun%(%name%, %algo%, %ax%, %ay%) %$$ cannot be called in $cref/parallel/ta_in_parallel/$$ mode. In addition, you cannot currently be recording $codei%AD<%Base%>%$$ operations when the constructor is called. This class is implemented as a derived class of $cref/atomic_base/atomic_ctor/atomic_base/$$ and hence some of its error message will refer to $code atomic_base$$. $head Base$$ The type $icode Base$$ specifies the base type for AD operations. $head ADVector$$ The type $icode ADVector$$ must be a $cref/simple vector class/SimpleVector/$$ with elements of type $codei%AD<%Base%>%$$. $head name$$ This $icode checkpoint$$ constructor argument has prototype $codei% const char* %name% %$$ It is the name used for error reporting. The suggested value for $icode name$$ is $icode afun$$; i.e., the same name as used for the function. $head ax$$ This argument has prototype $codei% const %ADVector%& %ax% %$$ and size must be equal to $icode n$$. It specifies vector $latex x \in B^n$$ at which an $codei%AD<%Base%>%$$ version of $latex y = f(x)$$ is to be evaluated. $head ay$$ This argument has prototype $codei% %ADVector%& %ay% %$$ Its input size must be equal to $icode m$$ and does not change. The input values of its elements do not matter. Upon return, it is an $codei%AD<%Base%>%$$ version of $latex y = f(x)$$. $head option$$ The $code option$$ syntax can be used to set the type of sparsity pattern used by $icode afun$$. This is an $codei%atomic_base<%Base%>%$$ function and its documentation can be found at $cref atomic_option$$. $head algo$$ The type of $icode algo$$ is arbitrary, except for the fact that the syntax $codei% %algo%(%ax%, %ay%) %$$ must evaluate the function $latex y = f(x)$$ using $codei%AD<%Base%>%$$ operations. In addition, we assume that the $cref/operation sequence/glossary/Operation/Sequence/$$ does not depend on the value of $icode ax$$. $head afun$$ Given $icode ax$$ it computes the corresponding value of $icode ay$$ using the operation sequence corresponding to $icode algo$$. If $codei%AD<%Base%>%$$ operations are being recorded, it enters the computation as single operation in the recording see $cref/start recording/Independent/Start Recording/$$. (Currently each use of $icode afun$$ actually corresponds to $icode%m%+%n%+2%$$ operations and creates $icode m$$ new variables, but this is not part of the CppAD specifications and my change.) $head clear$$ The $code atomic_base$$ class holds onto static work space in order to increase speed by avoiding system memory allocation calls. This call makes to work space $cref/available/ta_available/$$ to for other uses by the same thread. This should be called when you are done using the user atomic functions for a specific value of $icode Base$$. $subhead Restriction$$ The $code clear$$ routine cannot be called while in $cref/parallel/ta_in_parallel/$$ execution mode. $children% example/atomic/checkpoint.cpp %$$ $head Example$$ The file $cref checkpoint.cpp$$ contains an example and test of these operations. It returns true if it succeeds and false if it fails. $end */ template class checkpoint : public atomic_base { private: vector > f_; public: /*! Constructor of a checkpoint object \param name [in] is the user's name for the AD version of this atomic operation. \param algo [in/out] user routine that compute AD function values (not const because state may change during evaluation). \param ax [in] argument value where algo operation sequence is taped. \param ay [out] function value at specified argument value. */ template checkpoint(const char* name, Algo& algo, const ADVector& ax, ADVector& ay) : atomic_base(name) { CheckSimpleVector< CppAD::AD , ADVector>(); #ifdef _OPENMP #define NTHREADS omp_get_max_threads() #define THREAD omp_get_thread_num() #else #define NTHREADS 1 #define THREAD 0 #endif f_.resize(NTHREADS); // make a copy of ax because Independent modifies AD information ADVector x_tmp(ax); // delcare x_tmp as the independent variables Independent(x_tmp); // record mapping from x_tmp to ay algo(x_tmp, ay); // create function f_ : x -> y f_[0].Dependent(ay); // suppress checking for nan in f_ results // (see optimize documentation for atomic functions) f_[0].check_for_nan(false); // now optimize (we expect to use this function many times). f_[0].optimize(); // Copy for other threads for(size_t i=1;iafun(ax, ay). \tparam ADVector A simple vector class with elements of type AD. \param id optional parameter which must be zero if present. \param ax is the argument vector for this call, ax.size() determines the number of arguments. \param ay is the result vector for this call, ay.size() determines the number of results. */ template void operator()(const ADVector& ax, ADVector& ay, size_t id = 0) { CPPAD_ASSERT_KNOWN( id == 0, "checkpoint: id is non-zero in afun(ax, ay, id)" ); this->atomic_base::operator()(ax, ay, id); } /*! Link from user_atomic to forward mode \copydetails atomic_base::forward */ virtual bool forward( size_t p , size_t q , const vector& vx , vector& vy , const vector& tx , vector& ty ) { CPPAD_ASSERT_UNKNOWN( f_[THREAD].size_var() > 0 ); CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 ); CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 ); size_t n = tx.size() / (q+1); size_t m = ty.size() / (q+1); bool ok = true; size_t i, j; // 2DO: test both forward and reverse vy information if( vx.size() > 0 ) { //Compute Jacobian sparsity pattern. vector< std::set > s(m); if( n <= m ) { vector< std::set > r(n); for(j = 0; j < n; j++) r[j].insert(j); s = f_[THREAD].ForSparseJac(n, r); } else { vector< std::set > r(m); for(i = 0; i < m; i++) r[i].insert(i); s = f_[THREAD].RevSparseJac(m, r); } std::set::const_iterator itr; for(i = 0; i < m; i++) { vy[i] = false; for(itr = s[i].begin(); itr != s[i].end(); itr++) { j = *itr; assert( j < n ); // y[i] depends on the value of x[j] vy[i] |= vx[j]; } } } ty = f_.Forward(q, tx); // no longer need the Taylor coefficients in f_ // (have to reconstruct them every time) size_t c = 0; size_t r = 0; f_.capacity_order(c, r); return ok; } /*! Link from user_atomic to reverse mode \copydetails atomic_base::reverse */ virtual bool reverse( size_t q , const vector& tx , const vector& ty , vector& px , const vector& py ) { CPPAD_ASSERT_UNKNOWN( f_[THREAD].size_var() > 0 ); CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 ); CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 ); bool ok = true; // put proper forward mode coefficients in f_ # ifdef NDEBUG f_[THREAD].Forward(q, tx); # else size_t n = tx.size() / (q+1); size_t m = ty.size() / (q+1); CPPAD_ASSERT_UNKNOWN( px.size() == n * (q+1) ); CPPAD_ASSERT_UNKNOWN( py.size() == m * (q+1) ); size_t i, j, k; // vector check_ty = f_[THREAD].Forward(q, tx); for(i = 0; i < m; i++) { for(k = 0; k <= q; k++) { j = i * (q+1) + k; CPPAD_ASSERT_UNKNOWN( check_ty[j] == ty[j] ); } } # endif // now can run reverse mode px = f_[THREAD].Reverse(q+1, py); // no longer need the Taylor coefficients in f_ // (have to reconstruct them every time) size_t c = 0; size_t r = 0; f_[THREAD].capacity_order(c, r); return ok; } /*! Link from user_atomic to forward sparse Jacobian \copydetails atomic_base::for_sparse_jac */ virtual bool for_sparse_jac( size_t q , const vector< std::set >& r , vector< std::set >& s ) { bool ok = true; s = f_[THREAD].ForSparseJac(q, r); // no longer need the forward mode sparsity pattern // (have to reconstruct them every time) f_[THREAD].size_forward_set(0); return ok; } /*! Link from user_atomic to forward sparse Jacobian \copydetails atomic_base::for_sparse_jac */ virtual bool for_sparse_jac( size_t q , const vector& r , vector& s ) { bool ok = true; s = f_[THREAD].ForSparseJac(q, r); // no longer need the forward mode sparsity pattern // (have to reconstruct them every time) f_[THREAD].size_forward_bool(0); return ok; } /*! Link from user_atomic to forward sparse Jacobian \copydetails atomic_base::rev_sparse_jac */ virtual bool rev_sparse_jac( size_t q , const vector< std::set >& rt , vector< std::set >& st ) { bool ok = true; // compute rt // 2DO: remove need for nz_compare all the time. It is only really // necessary when optimizer calls this member function. bool transpose = true; bool nz_compare = true; st = f_[THREAD].RevSparseJac(q, rt, transpose, nz_compare); return ok; } /*! Link from user_atomic to forward sparse Jacobian \copydetails atomic_base::rev_sparse_jac */ virtual bool rev_sparse_jac( size_t q , const vector& rt , vector& st ) { bool ok = true; // compute rt bool transpose = true; bool nz_compare = true; // 2DO: remove need for nz_compare all the time. It is only really // necessary when optimizer calls this member function. st = f_[THREAD].RevSparseJac(q, rt, transpose, nz_compare); return ok; } /*! Link from user_atomic to forward sparse Jacobian \copydetails atomic_base::rev_sparse_hes */ virtual bool rev_sparse_hes( const vector& vx , const vector& s , vector& t , size_t q , const vector< std::set >& r , const vector< std::set >& u , vector< std::set >& v ) { size_t n = v.size(); size_t m = u.size(); CPPAD_ASSERT_UNKNOWN( r.size() == v.size() ); CPPAD_ASSERT_UNKNOWN( s.size() == m ); CPPAD_ASSERT_UNKNOWN( t.size() == n ); bool ok = true; bool transpose = true; std::set::const_iterator itr; // compute sparsity pattern for T(x) = S(x) * f'(x) t = f_[THREAD].RevSparseJac(1, s); # ifndef NDEBUG for(size_t j = 0; j < n; j++) CPPAD_ASSERT_UNKNOWN( vx[j] || ! t[j] ) # endif // V(x) = f'(x)^T * g''(y) * f'(x) * R + g'(y) * f''(x) * R // U(x) = g''(y) * f'(x) * R // S(x) = g'(y) // compute sparsity pattern for A(x) = f'(x)^T * U(x) vector< std::set > a(n); a = f_[THREAD].RevSparseJac(q, u, transpose); // set version of s vector< std::set > set_s(1); CPPAD_ASSERT_UNKNOWN( set_s[0].empty() ); size_t i; for(i = 0; i < m; i++) if( s[i] ) set_s[0].insert(i); // compute sparsity pattern for H(x) = (S(x) * F)''(x) * R // (store it in v) f_[THREAD].ForSparseJac(q, r); v = f_[THREAD].RevSparseHes(q, set_s, transpose); // compute sparsity pattern for V(x) = A(x) + H(x) for(i = 0; i < n; i++) { for(itr = a[i].begin(); itr != a[i].end(); itr++) { size_t j = *itr; CPPAD_ASSERT_UNKNOWN( j < q ); v[i].insert(j); } } // no longer need the forward mode sparsity pattern // (have to reconstruct them every time) f_[THREAD].size_forward_set(0); return ok; } /*! Link from user_atomic to forward sparse Jacobian \copydetails atomic_base::rev_sparse_hes */ virtual bool rev_sparse_hes( const vector& vx , const vector& s , vector& t , size_t q , const vector& r , const vector& u , vector& v ) { CPPAD_ASSERT_UNKNOWN( r.size() == v.size() ); CPPAD_ASSERT_UNKNOWN( s.size() == u.size() / q ); CPPAD_ASSERT_UNKNOWN( t.size() == v.size() / q ); size_t n = t.size(); bool ok = true; bool transpose = true; std::set::const_iterator itr; size_t i, j; // compute sparsity pattern for T(x) = S(x) * f'(x) t = f_[THREAD].RevSparseJac(1, s); # ifndef NDEBUG for(j = 0; j < n; j++) CPPAD_ASSERT_UNKNOWN( vx[j] || ! t[j] ) # endif // V(x) = f'(x)^T * g''(y) * f'(x) * R + g'(y) * f''(x) * R // U(x) = g''(y) * f'(x) * R // S(x) = g'(y) // compute sparsity pattern for A(x) = f'(x)^T * U(x) vector a(n * q); a = f_[THREAD].RevSparseJac(q, u, transpose); // compute sparsity pattern for H(x) =(S(x) * F)''(x) * R // (store it in v) f_[THREAD].ForSparseJac(q, r); v = f_[THREAD].RevSparseHes(q, s, transpose); // compute sparsity pattern for V(x) = A(x) + H(x) for(i = 0; i < n; i++) { for(j = 0; j < q; j++) v[ i * q + j ] |= a[ i * q + j]; } // no longer need the forward mode sparsity pattern // (have to reconstruct them every time) f_[THREAD].size_forward_set(0); return ok; } }; } // END_CPPAD_NAMESPACE # endif #undef NTHREADS #undef THREAD TMB/inst/include/cppad/local/sign_op.hpp0000644000176200001440000000732314536067013017636 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SIGN_OP_INCLUDED # define CPPAD_SIGN_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file sign_op.hpp Forward and reverse mode calculations for z = sign(x). */ /*! Compute forward mode Taylor coefficient for result of op = SignOp. The C++ source code corresponding to this operation is \verbatim z = sign(x) \endverbatim \copydetails forward_unary1_op */ template inline void forward_sign_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; if( p == 0 ) { z[0] = sign(x[0]); p++; } for(size_t j = p; j <= q; j++) z[j] = Base(0.); } /*! Multiple direction forward mode Taylor coefficient for op = SignOp. The C++ source code corresponding to this operation is \verbatim z = sign(x) \endverbatim \copydetails forward_unary1_op_dir */ template inline void forward_sign_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; size_t m = (q - 1) * r + 1; Base* z = taylor + i_z * num_taylor_per_var; for(size_t ell = 0; ell < r; ell++) z[m+ell] = Base(0.); } /*! Compute zero order forward mode Taylor coefficient for result of op = SignOp. The C++ source code corresponding to this operation is \verbatim z = sign(x) \endverbatim \copydetails forward_unary1_op_0 */ template inline void forward_sign_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base x0 = *(taylor + i_x * cap_order); Base* z = taylor + i_z * cap_order; z[0] = sign(x0); } /*! Compute reverse mode partial derivatives for result of op = SignOp. The C++ source code corresponding to this operation is \verbatim z = sign(x) \endverbatim \copydetails reverse_unary1_op */ template inline void reverse_sign_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // nothing to do because partials of sign are zero return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/for_jac_sweep.hpp0000644000176200001440000005003514536067013021004 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_FOR_JAC_SWEEP_INCLUDED # define CPPAD_FOR_JAC_SWEEP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file for_jac_sweep.hpp Compute Forward mode Jacobian sparsity patterns. */ /*! \def CPPAD_FOR_JAC_SWEEP_TRACE This value is either zero or one. Zero is the normal operational value. If it is one, a trace of every for_jac_sweep computation is printed. */ # define CPPAD_FOR_JAC_SWEEP_TRACE 0 /* \def CPPAD_ATOMIC_CALL This avoids warnings when NDEBUG is defined and user_ok is not used. If \c NDEBUG is defined, this resolves to \code user_atom->for_sparse_jac \endcode otherwise, it respolves to \code user_ok = user_atom->for_sparse_jac \endcode This maco is undefined at the end of this file to facillitate is use with a different definition in other files. */ # ifdef NDEBUG # define CPPAD_ATOMIC_CALL user_atom->for_sparse_jac # else # define CPPAD_ATOMIC_CALL user_ok = user_atom->for_sparse_jac # endif /*! Given the sparsity pattern for the independent variables, ForJacSweep computes the sparsity pattern for all the other variables. \tparam Base base type for the operator; i.e., this operation sequence was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param n is the number of independent variables on the tape. \param numvar is the total number of variables on the tape; i.e., \a play->num_var_rec(). \param play The information stored in \a play is a recording of the operations corresponding to a function \f[ F : {\bf R}^n \rightarrow {\bf R}^m \f] where \f$ n \f$ is the number of independent variables and \f$ m \f$ is the number of dependent variables. The object \a play is effectly constant. It is not declared const because while playing back the tape the object \a play holds information about the currentl location with in the tape and this changes during playback. \param var_sparsity \b Input: For j = 1 , ... , \a n, the sparsity pattern for the independent variable with index (j-1) corresponds to the set with index j in \a var_sparsity. \n \n \b Output: For i = \a n + 1 , ... , \a numvar - 1, the sparsity pattern for the variable with index i on the tape corresponds to the set with index i in \a var_sparsity. \par Checked Assertions: \li numvar == var_sparsity.n_set() \li numvar == play->num_var_rec() */ template void ForJacSweep( size_t n , size_t numvar , player* play , Vector_set& var_sparsity ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; size_t i, j, k; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar ); // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // cum_sparsity accumulates sparsity pattern a cummulative sum size_t limit = var_sparsity.end(); // vecad_sparsity contains a sparsity pattern from each VecAD object // to all the other variables. // vecad_ind maps a VecAD index (the beginning of the // VecAD object) to its from index in vecad_sparsity size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparsity; vecad_sparsity.resize(num_vecad_vec, limit); pod_vector vecad_ind; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set to proper index for this VecAD vecad_ind[j] = i; for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // invalid index // start of next VecAD j += length + 1; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // -------------------------------------------------------------- // work space used by UserOp. // typedef std::set size_set; size_set::iterator set_itr; // iterator for a standard set size_set::iterator set_end; // end of iterator sequence vector< size_set > set_r; // set sparsity pattern for the argument x vector< size_set > set_s; // set sparisty pattern for the result y // vector bool_r; // bool sparsity pattern for the argument x vector bool_s; // bool sparisty pattern for the result y // const size_t user_q = limit; // maximum element plus one size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // user's atomic op calculator bool user_bool = false; // use bool or set sparsity ? # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_start; // -------------------------------------------------------------- # if CPPAD_FOR_JAC_SWEEP_TRACE Rcout << std::endl; CppAD::vectorBool z_value(limit); # endif // skip the BeginOp at the beginning of the recording play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); bool more_operators = true; while(more_operators) { // this op play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var); // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case CSkipOp: // CSipOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. play->forward_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_sparse_jacobian_csum_op( i_var, arg, var_sparsity ); play->forward_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case CExpOp: forward_sparse_jacobian_cond_op( i_var, arg, num_par, var_sparsity ); break; // -------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); var_sparsity.clear(i_var); break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[0] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); // sparsity pattern is already defined break; // ------------------------------------------------- case LdpOp: forward_sparse_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case LdvOp: forward_sparse_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); var_sparsity.clear(i_var); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); break; // ------------------------------------------------- case SignOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case StppOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); // storing a parameter does not affect vector sparsity break; // ------------------------------------------------- case StpvOp: forward_sparse_store_op( op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case StvpOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); // storing a parameter does not affect vector sparsity break; // ------------------------------------------------- case StvvOp: forward_sparse_store_op( op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_bool = user_atom->sparsity() == atomic_base::bool_sparsity_enum; if( user_bool ) { if( bool_r.size() != user_n * user_q ) bool_r.resize( user_n * user_q ); if( bool_s.size() != user_m * user_q ) bool_s.resize( user_m * user_q ); for(i = 0; i < user_n; i++) for(j = 0; j < user_q; j++) bool_r[ i * user_q + j] = false; } else { if(set_r.size() != user_n ) set_r.resize(user_n); if(set_s.size() != user_m ) set_s.resize(user_m); for(i = 0; i < user_n; i++) set_r[i].clear(); } user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base::class_name(user_index) + ": atomic_base.for_sparse_jac: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_state = user_start; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); // set row user_j to empty sparsity pattern ++user_j; if( user_j == user_n ) { // call users function for this operation user_atom->set_id(user_id); if( user_bool ) CPPAD_ATOMIC_CALL( user_q, bool_r, bool_s ); else CPPAD_ATOMIC_CALL( user_q, set_r, set_s ); user_state = user_ret; } break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); // set row user_j to sparsity pattern for variable arg[0] var_sparsity.begin(arg[0]); i = var_sparsity.next_element(); while( i < user_q ) { if( user_bool ) bool_r[user_j * user_q + i] = true; else set_r[user_j].insert(i); i = var_sparsity.next_element(); } ++user_j; if( user_j == user_n ) { // call users function for this operation user_atom->set_id(user_id); if( user_bool ) CPPAD_ATOMIC_CALL( user_q, bool_r, bool_s ); else CPPAD_ATOMIC_CALL( user_q, set_r, set_s ); user_state = user_ret; } break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); // It might be faster if we add set union to var_sparsity // where one of the sets is not in var_sparsity if( user_bool ) { for(j = 0; j < user_q; j++) if( bool_s[ user_i * user_q + j ] ) var_sparsity.add_element(i_var, j); } else { set_itr = set_s[user_i].begin(); set_end = set_s[user_i].end(); while( set_itr != set_end ) var_sparsity.add_element(i_var, *set_itr++); } user_i++; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FOR_JAC_SWEEP_TRACE const addr_t* arg_tmp = arg; if( op == CSumOp ) arg_tmp = arg - arg[-1] - 4; if( op == CSkipOp ) arg_tmp = arg - arg[-1] - 7; // // value for this variable for(j = 0; j < limit; j++) z_value[j] = false; var_sparsity.begin(i_var); j = var_sparsity.next_element(); while( j < limit ) { z_value[j] = true; j = var_sparsity.next_element(); } printOp( Rcout, play, i_op, i_var, op, arg_tmp ); if( NumRes(op) > 0 ) printOpResult( Rcout, 1, &z_value, 0, (CppAD::vectorBool *) CPPAD_NULL ); Rcout << std::endl; } Rcout << std::endl; # else } # endif CPPAD_ASSERT_UNKNOWN( i_var + 1 == play->num_var_rec() ); return; } } // END_CPPAD_NAMESPACE // preprocessor symbols that are local to this file # undef CPPAD_FOR_JAC_SWEEP_TRACE # undef CPPAD_ATOMIC_CALL # endif TMB/inst/include/cppad/local/atan_op.hpp0000644000176200001440000001404714536067013017622 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ATAN_OP_INCLUDED # define CPPAD_ATAN_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file atan_op.hpp Forward and reverse mode calculations for z = atan(x). */ /*! Forward mode Taylor coefficient for result of op = AtanOp. The C++ source code corresponding to this operation is \verbatim z = atan(x) \endverbatim The auxillary result is \verbatim y = 1 + x * x \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op */ template inline void forward_atan_op( size_t p , size_t q , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; Base* b = z - cap_order; // called y in documentation size_t k; if( p == 0 ) { z[0] = atan( x[0] ); b[0] = Base(1) + x[0] * x[0]; p++; } for(size_t j = p; j <= q; j++) { b[j] = Base(2) * x[0] * x[j]; z[j] = Base(0); for(k = 1; k < j; k++) { b[j] += x[k] * x[j-k]; z[j] -= Base(k) * z[k] * b[j-k]; } z[j] /= Base(j); z[j] += x[j]; z[j] /= b[0]; } } /*! Multiple direction Taylor coefficient for op = AtanOp. The C++ source code corresponding to this operation is \verbatim z = atan(x) \endverbatim The auxillary result is \verbatim y = 1 + x * x \endverbatim The value of y, and its derivatives, are computed along with the value and derivatives of z. \copydetails forward_unary2_op_dir */ template inline void forward_atan_op_dir( size_t q , size_t r , size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to argument and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* x = taylor + i_x * num_taylor_per_var; Base* z = taylor + i_z * num_taylor_per_var; Base* b = z - num_taylor_per_var; // called y in documentation size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) { b[m+ell] = Base(2) * x[m+ell] * x[0]; z[m+ell] = Base(q) * x[m+ell]; for(size_t k = 1; k < q; k++) { b[m+ell] += x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell]; z[m+ell] -= Base(k) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell]; } z[m+ell] /= ( Base(q) * b[0] ); } } /*! Zero order forward mode Taylor coefficient for result of op = AtanOp. The C++ source code corresponding to this operation is \verbatim z = atan(x) \endverbatim The auxillary result is \verbatim y = 1 + x * x \endverbatim The value of y is computed along with the value of z. \copydetails forward_unary2_op_0 */ template inline void forward_atan_op_0( size_t i_z , size_t i_x , size_t cap_order , Base* taylor ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( 0 < cap_order ); // Taylor coefficients corresponding to argument and result Base* x = taylor + i_x * cap_order; Base* z = taylor + i_z * cap_order; Base* b = z - cap_order; // called y in documentation z[0] = atan( x[0] ); b[0] = Base(1) + x[0] * x[0]; } /*! Reverse mode partial derivatives for result of op = AtanOp. The C++ source code corresponding to this operation is \verbatim z = atan(x) \endverbatim The auxillary result is \verbatim y = 1 + x * x \endverbatim The value of y is computed along with the value of z. \copydetails reverse_unary2_op */ template inline void reverse_atan_op( size_t d , size_t i_z , size_t i_x , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partials corresponding to argument const Base* x = taylor + i_x * cap_order; Base* px = partial + i_x * nc_partial; // Taylor coefficients and partials corresponding to first result const Base* z = taylor + i_z * cap_order; Base* pz = partial + i_z * nc_partial; // Taylor coefficients and partials corresponding to auxillary result const Base* b = z - cap_order; // called y in documentation Base* pb = pz - nc_partial; // If pz is zero, make sure this operation has no effect // (zero times infinity or nan would be non-zero). bool skip(true); for(size_t i_d = 0; i_d <= d; i_d++) skip &= IdenticalZero(pz[i_d]); if( skip ) return; // number of indices to access size_t j = d; size_t k; while(j) { // scale partials w.r.t z[j] and b[j] pz[j] /= b[0]; pb[j] *= Base(2); pb[0] -= pz[j] * z[j]; px[j] += pz[j] + pb[j] * x[0]; px[0] += pb[j] * x[j]; // more scaling of partials w.r.t z[j] pz[j] /= Base(j); for(k = 1; k < j; k++) { pb[j-k] -= pz[j] * Base(k) * z[k]; pz[k] -= pz[j] * Base(k) * b[j-k]; px[k] += pb[j] * x[j-k]; } --j; } px[0] += pz[0] / b[0] + pb[0] * Base(2) * x[0]; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/optimize.hpp0000644000176200001440000025615014536067013020044 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_OPTIMIZE_INCLUDED # define CPPAD_OPTIMIZE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin optimize$$ $spell jac bool Taylor var CppAD cppad std CondExpEq $$ $section Optimize an ADFun Object Tape$$ $index optimize$$ $index tape, optimize$$ $index sequence, optimize operations$$ $index operations, optimize sequence$$ $index speed, optimize$$ $index memory, optimize$$ $head Syntax$$ $icode%f%.optimize()%$$ $head Purpose$$ The operation sequence corresponding to an $cref ADFun$$ object can be very large and involve many operations; see the size functions in $cref seq_property$$. The $icode%f%.optimize%$$ procedure reduces the number of operations, and thereby the time and the memory, required to compute function and derivative values. $head f$$ The object $icode f$$ has prototype $codei% ADFun<%Base%> %f% %$$ $head Improvements$$ You can see the reduction in number of variables in the operation sequence by calling the function $cref/f.size_var()/seq_property/size_var/$$ before and after the optimization procedure. Given that the optimization procedure takes time, it may be faster to skip this optimize procedure and just compute derivatives using the original operation sequence. $subhead Testing$$ You can run the CppAD $cref/speed/speed_main/$$ tests and see the corresponding changes in number of variables and execution time; see $cref cmake_check$$. $head Efficiency$$ The $code optimize$$ member function may greatly reduce the number of variables in the operation sequence; see $cref/size_var/seq_property/size_var/$$. If a $cref/zero order forward/forward_zero/$$ calculation is done during the construction of $icode f$$, it will require more memory and time than required after the optimization procedure. In addition, it will need to be redone. For this reason, it is more efficient to use $codei% ADFun<%Base%> %f%; %f%.Dependent(%x%, %y%); %f%.optimize(); %$$ instead of $codei% ADFun<%Base%> %f%(%x%, %y%) %f%.optimize(); %$$ See the discussion about $cref/sequence constructors/FunConstruct/Sequence Constructor/$$. $head Atomic Functions$$ There are some subtitle issue with optimized $cref atomic$$ functions $latex v = g(u)$$: $subhead rev_sparse_jac$$ The $cref atomic_rev_sparse_jac$$ function is be used to determine which components of $icode u$$ affect the dependent variables of $icode f$$. The current setting of the $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for each atomic function is used to determine if the $code bool$$ or $code std::set$$ version of $cref atomic_rev_sparse_jac$$ is used. $subhead nan$$ If $icode%u%[%i%]%$$ does not affect the value of the dependent variables for $icode f$$, the value of $icode%u%[%i%]%$$ is set to $cref nan$$. $head Checking Optimization$$ $index NDEBUG$$ If $cref/NDEBUG/Faq/Speed/NDEBUG/$$ is not defined, and $cref/f.size_order()/size_order/$$ is greater than zero, a $cref forward_zero$$ calculation is done using the optimized version of $icode f$$ and the results are checked to see that they are the same as before. If they are not the same, the $cref ErrorHandler$$ is called with a known error message related to $icode%f%.optimize()%$$. $head Example$$ $children% example/optimize.cpp %$$ The file $cref optimize.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE namespace optimize { // BEGIN_CPPAD_OPTIMIZE_NAMESPACE /*! \file optimize.hpp Routines for optimizing a tape */ /*! State for this variable set during reverse sweep. */ enum enum_connect_type { /// There is no operation that connects this variable to the /// independent variables. not_connected , /// There is one or more operations that connects this variable to the /// independent variables. yes_connected , /// There is only one parrent that connects this variable to the /// independent variables and the parent is a summation operation; i.e., /// AddvvOp, AddpvOp, SubpvOp, SubvpOp, or SubvvOp. sum_connected , /// Satisfies the sum_connected assumptions above and in addition /// this variable is the result of summation operator. csum_connected , /// This node is only connected in the case where the comparision is /// true for the conditional expression with index \c connect_index. cexp_connected }; /*! Class used to hold information about one conditional expression. */ class class_cexp_pair { public: /// packs both the compare and index information /// compare = pack_ % 2 /// index = pack_ / 2 size_t pack_; /// If this is true (false) this connection is only for the case where /// the comparision in the conditional expression is true (false) bool compare(void) const { return bool(pack_ % 2); } /// This is the index of the conditional expression (in cksip_info) /// for this connection size_t index(void) const { return pack_ / 2; } /// constructor class_cexp_pair(const bool& compare_arg, const size_t& index_arg) : pack_(size_t(compare_arg) + 2 * index_arg ) { CPPAD_ASSERT_UNKNOWN( compare_arg == compare() ); CPPAD_ASSERT_UNKNOWN( index_arg == index() ); } /// assignment operator void operator=(const class_cexp_pair& right) { pack_ = right.pack_; } /// not equal operator bool operator!=(const class_cexp_pair& right) { return pack_ != right.pack_; } /// Less than operator /// (required for intersection of two sets of class_cexp_pair elements). bool operator<(const class_cexp_pair& right) const { return pack_ < right.pack_; } }; /*! A container that is like std::set except that it does not allocate empty sets and only has a few operations. */ class class_set_cexp_pair { private: // This set is empty if and only if ptr_ == CPPAD_NULL; std::set* ptr_; void new_ptr(void) { CPPAD_ASSERT_UNKNOWN( ptr_ == CPPAD_NULL ); ptr_ = new std::set; CPPAD_ASSERT_UNKNOWN( ptr_ != CPPAD_NULL ); // Rcout << "new ptr_ = " << ptr_ << std::endl; } void delete_ptr(void) { if( ptr_ != CPPAD_NULL ) { // Rcout << "delete ptr_ = " << ptr_ << std::endl; delete ptr_; } ptr_ = CPPAD_NULL; } public: /// constructor class_set_cexp_pair(void) { ptr_ = CPPAD_NULL; } /// destructor ~class_set_cexp_pair(void) { delete_ptr(); } void print(void) { if( ptr_ == CPPAD_NULL ) { Rcout << "{ }"; return; } CPPAD_ASSERT_UNKNOWN( ! empty() ); const char* sep = "{ "; std::set::const_iterator itr; for(itr = ptr_->begin(); itr != ptr_->end(); itr++) { Rcout << sep; Rcout << "(" << itr->compare() << "," << itr->index() << ")"; sep = ", "; } Rcout << "}"; } /// assignment operator void operator=(const class_set_cexp_pair& other) { // make this a copy of the other set if( other.ptr_ == CPPAD_NULL ) { if( ptr_ == CPPAD_NULL ) return; delete_ptr(); return; } CPPAD_ASSERT_UNKNOWN( ! other.empty() ); if( ptr_ == CPPAD_NULL ) new_ptr(); *ptr_ = *other.ptr_; } /// insert an element in this set void insert(const class_cexp_pair& element) { if( ptr_ == CPPAD_NULL ) new_ptr(); ptr_->insert(element); CPPAD_ASSERT_UNKNOWN( ! empty() ); } /// is this set empty bool empty(void) const { if( ptr_ == CPPAD_NULL ) return true; CPPAD_ASSERT_UNKNOWN( ! ptr_->empty() ); return false; } /// remove the elements in this set void clear(void) { if( ptr_ == CPPAD_NULL ) return; CPPAD_ASSERT_UNKNOWN( ! empty() ); delete_ptr(); } // returns begin pointer for the set std::set::const_iterator begin(void) { CPPAD_ASSERT_UNKNOWN( ! empty() ); return ptr_->begin(); } // returns end pointer for the set std::set::const_iterator end(void) { CPPAD_ASSERT_UNKNOWN( ! empty() ); return ptr_->end(); } /*! Make this set the intersection of itself with another set. \param other the other set */ void intersection(const class_set_cexp_pair& other ) { // empty result case if( ptr_ == CPPAD_NULL ) return; // empty result case if( other.ptr_ == CPPAD_NULL ) { delete_ptr(); return; } // put result here class_set_cexp_pair result; CPPAD_ASSERT_UNKNOWN( result.ptr_ == CPPAD_NULL ); result.new_ptr(); CPPAD_ASSERT_UNKNOWN( result.ptr_ != CPPAD_NULL ); // do the intersection std::set_intersection( ptr_->begin() , ptr_->end() , other.ptr_->begin() , other.ptr_->end() , std::inserter(*result.ptr_, result.ptr_->begin()) ); if( result.ptr_->empty() ) result.delete_ptr(); // swap this and the result std::swap(ptr_, result.ptr_); return; } }; /*! Structure used by \c optimize to hold information about one variable. in the old operation seqeunce. */ struct struct_old_variable { /// Operator for which this variable is the result, \c NumRes(op) > 0. /// Set by the reverse sweep at beginning of optimization. OpCode op; /// Pointer to first argument (child) for this operator. /// Set by the reverse sweep at beginning of optimization. const addr_t* arg; /// How is this variable connected to the independent variables enum_connect_type connect_type; /// New operation sequence corresponding to this old varable. /// Set during forward sweep to the index in the new tape addr_t new_var; /// New operator index for this varable. /// Set during forward sweep to the index in the new tape size_t new_op; /// Did this variable match another variable in the operation sequence bool match; }; struct struct_size_pair { size_t i_op; // an operator index size_t i_var; // a variable index }; /*! Structures used by \c record_csum to hold information about one variable. */ struct struct_csum_variable { /// Operator for which this variable is the result, \c NumRes(op) > 0. OpCode op; /// Pointer to first argument (child) for this operator. /// Set by the reverse sweep at beginning of optimization. const addr_t* arg; /// Is this variable added to the summation /// (if not it is subtracted) bool add; }; /*! Structure used to pass work space from \c optimize to \c record_csum (so that stacks do not start from zero size every time). */ struct struct_csum_stacks { /// stack of operations in the cummulative summation std::stack op_stack; /// stack of variables to be added std::stack add_stack; /// stack of variables to be subtracted std::stack sub_stack; }; /*! CExpOp information that is copied to corresponding CSkipOp */ struct struct_cskip_info { /// comparision operator CompareOp cop; /// (flag & 1) is true if and only if left is a variable /// (flag & 2) is true if and only if right is a variable size_t flag; /// index for left comparison operand size_t left; /// index for right comparison operand size_t right; /// maximum variable index between left and right size_t max_left_right; /// set of variables to skip on true CppAD::vector skip_var_true; /// set of variables to skip on false CppAD::vector skip_var_false; /// set of operations to skip on true CppAD::vector skip_op_true; /// set of operations to skip on false CppAD::vector skip_op_false; /// size of skip_op_true size_t n_op_true; /// size of skip_op_false size_t n_op_false; /// index in the argument recording of first argument for this CSkipOp size_t i_arg; }; /*! Connection information for a user atomic function */ struct struct_user_info { /// type of connection for this atomic function enum_connect_type connect_type; /// If this is an conditional connection, this is the information /// of the correpsonding CondExpOp operators class_set_cexp_pair cexp_set; /// If this is a conditional connection, this is the operator /// index of the beginning of the atomic call sequence; i.e., /// the first UserOp. size_t op_begin; /// If this is a conditional connection, this is one more than the /// operator index of the ending of the atomic call sequence; i.e., /// the second UserOp. size_t op_end; }; /*! Shared documentation for optimization helper functions (not called). \param tape is a vector that maps a variable index, in the old operation sequence, to an struct_old_variable information record. Note that the index for this vector must be greater than or equal zero and less than tape.size(). \li tape[i].op is the operator in the old operation sequence corresponding to the old variable index \c i. Assertion: NumRes(tape[i].op) > 0. \li tape[i].arg for j < NumArg( tape[i].op ), tape[i].arg[j] is the j-th the argument, in the old operation sequence, corresponding to the old variable index \c i. Assertion: tape[i].arg[j] < i. \li tape[i].new_var Suppose i <= current, j < NumArg( tape[i].op ), and k = tape[i].arg[j], and \c j corresponds to a variable for operator tape[i].op. It follows that tape[k].new_var has alread been set to the variable in the new operation sequence corresponding to the old variable index \c k. This means that the \c new_var value has been set for all the possible arguments that come before \a current. \param current is the index in the old operation sequence for the variable corresponding to the result for the current operator. Assertions: current < tape.size(), NumRes( tape[current].op ) > 0. \param npar is the number of parameters corresponding to this operation sequence. \param par is a vector of length \a npar containing the parameters for this operation sequence; i.e., given a parameter index \c i, the corresponding parameter value is par[i]. */ template void prototype( const CppAD::vector& tape , size_t current , size_t npar , const Base* par ) { CPPAD_ASSERT_UNKNOWN(false); } /*! Check a unary operator for a complete match with a previous operator. A complete match means that the result of the previous operator can be used inplace of the result for current operator. \param tape is a vector that maps a variable index, in the old operation sequence, to an struct_old_variable information record. Note that the index for this vector must be greater than or equal zero and less than tape.size(). \li tape[i].op is the operator in the old operation sequence corresponding to the old variable index \c i. Assertion: NumRes(tape[i].op) > 0. \li tape[i].arg for j < NumArg( tape[i].op ), tape[i].arg[j] is the j-th the argument, in the old operation sequence, corresponding to the old variable index \c i. Assertion: tape[i].arg[j] < i. \li tape[i].new_var Suppose i <= current, j < NumArg( tape[i].op ), and k = tape[i].arg[j], and \c j corresponds to a variable for operator tape[i].op. It follows that tape[k].new_var has alread been set to the variable in the new operation sequence corresponding to the old variable index \c k. This means that the \c new_var value has been set for all the possible arguments that come before \a current. \param current is the index in the old operation sequence for the variable corresponding to the result for the current operator. Assertions: current < tape.size(), NumRes( tape[current].op ) > 0. \param npar is the number of parameters corresponding to this operation sequence. \param par is a vector of length \a npar containing the parameters for this operation sequence; i.e., given a parameter index \c i, the corresponding parameter value is par[i]. \param hash_table_var is a vector with size CPPAD_HASH_TABLE_SIZE that maps a hash code to the corresponding variable index in the old operation sequence. All the values in this table must be less than \a current. \param code The input value of code does not matter. The output value of code is the hash code corresponding to this operation in the new operation sequence. \return If the return value is zero, no match was found. If the return value is greater than zero, it is the old operation sequence index of a variable, that comes before current and can be used to replace the current variable. \par Restrictions: NumArg( tape[current].op ) == 1 */ template addr_t unary_match( const CppAD::vector& tape , size_t current , size_t npar , const Base* par , const CppAD::vector& hash_table_var , unsigned short& code ) { const addr_t* arg = tape[current].arg; OpCode op = tape[current].op; addr_t new_arg[1]; // ErfOp has three arguments, but the second and third are always the // parameters 0 and 2 / sqrt(pi) respectively. CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 || op == ErfOp); CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < current ); new_arg[0] = tape[arg[0]].new_var; CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < current ); code = hash_code( op , new_arg , npar , par ); size_t i_var = hash_table_var[code]; CPPAD_ASSERT_UNKNOWN( i_var < current ); if( op == tape[i_var].op ) { size_t k = tape[i_var].arg[0]; CPPAD_ASSERT_UNKNOWN( k < i_var ); if (new_arg[0] == tape[k].new_var ) return i_var; } return 0; } /*! Check a binary operator for a complete match with a previous operator, \param tape is a vector that maps a variable index, in the old operation sequence, to an struct_old_variable information record. Note that the index for this vector must be greater than or equal zero and less than tape.size(). \li tape[i].op is the operator in the old operation sequence corresponding to the old variable index \c i. Assertion: NumRes(tape[i].op) > 0. \li tape[i].arg for j < NumArg( tape[i].op ), tape[i].arg[j] is the j-th the argument, in the old operation sequence, corresponding to the old variable index \c i. Assertion: tape[i].arg[j] < i. \li tape[i].new_var Suppose i <= current, j < NumArg( tape[i].op ), and k = tape[i].arg[j], and \c j corresponds to a variable for operator tape[i].op. It follows that tape[k].new_var has alread been set to the variable in the new operation sequence corresponding to the old variable index \c k. This means that the \c new_var value has been set for all the possible arguments that come before \a current. \param current is the index in the old operation sequence for the variable corresponding to the result for the current operator. Assertions: current < tape.size(), NumRes( tape[current].op ) > 0. \param npar is the number of parameters corresponding to this operation sequence. \param par is a vector of length \a npar containing the parameters for this operation sequence; i.e., given a parameter index \c i, the corresponding parameter value is par[i]. \param hash_table_var is a vector with size CPPAD_HASH_TABLE_SIZE that maps a hash code to the corresponding variable index in the old operation sequence. All the values in this table must be less than \a current. \param code The input value of code does not matter. The output value of code is the hash code corresponding to this operation in the new operation sequence. \return If the return value is zero, no match was found. If the return value is greater than zero, it is the index of a new variable that can be used to replace the old variable. \par Restrictions: The binary operator must be an addition, subtraction, multiplication, division or power operator. NumArg( tape[current].op ) == 1. */ template inline addr_t binary_match( const CppAD::vector& tape , size_t current , size_t npar , const Base* par , const CppAD::vector& hash_table_var , unsigned short& code ) { OpCode op = tape[current].op; const addr_t* arg = tape[current].arg; addr_t new_arg[2]; bool parameter[2]; // initialize return value addr_t match_var = 0; CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 ); switch(op) { // index op variable case DisOp: // parameter not defined for this case CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current ); new_arg[0] = arg[0]; new_arg[1] = tape[arg[1]].new_var; break; // parameter op variable ---------------------------------- case AddpvOp: case MulpvOp: case DivpvOp: case PowpvOp: case SubpvOp: // arg[0] parameter[0] = true; new_arg[0] = arg[0]; CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < npar ); // arg[1] parameter[1] = false; new_arg[1] = tape[arg[1]].new_var; CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current ); break; // variable op parameter ----------------------------------- case DivvpOp: case PowvpOp: case SubvpOp: // arg[0] parameter[0] = false; new_arg[0] = tape[arg[0]].new_var; CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < current ); // arg[1] parameter[1] = true; new_arg[1] = arg[1]; CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < npar ); break; // variable op variable ----------------------------------- case AddvvOp: case MulvvOp: case DivvvOp: case PowvvOp: case SubvvOp: // arg[0] parameter[0] = false; new_arg[0] = tape[arg[0]].new_var; CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < current ); // arg[1] parameter[1] = false; new_arg[1] = tape[arg[1]].new_var; CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current ); break; // must be one of the cases above default: CPPAD_ASSERT_UNKNOWN(false); } code = hash_code( op , new_arg , npar , par ); size_t i_var = hash_table_var[code]; CPPAD_ASSERT_UNKNOWN( i_var < current ); if( op == tape[i_var].op ) { bool match = true; if( op == DisOp ) { match &= new_arg[0] == tape[i_var].arg[0]; size_t k = tape[i_var].arg[1]; match &= new_arg[1] == tape[k].new_var; } else { for(size_t j = 0; j < 2; j++) { size_t k = tape[i_var].arg[j]; if( parameter[j] ) { CPPAD_ASSERT_UNKNOWN( k < npar ); match &= IdenticalEqualPar( par[ arg[j] ], par[k] ); } else { CPPAD_ASSERT_UNKNOWN( k < i_var ); match &= (new_arg[j] == tape[k].new_var); } } } if( match ) match_var = i_var; } if( (match_var > 0) | ( (op != AddvvOp) & (op != MulvvOp ) ) ) return match_var; // check for match with argument order switched ---------------------- CPPAD_ASSERT_UNKNOWN( op == AddvvOp || op == MulvvOp ); std::swap(new_arg[0], new_arg[1]); unsigned short code_switch = hash_code( op , new_arg , npar , par ); i_var = hash_table_var[code_switch]; CPPAD_ASSERT_UNKNOWN( i_var < current ); if( op == tape[i_var].op ) { bool match = true; size_t j; for(j = 0; j < 2; j++) { size_t k = tape[i_var].arg[j]; CPPAD_ASSERT_UNKNOWN( k < i_var ); match &= (new_arg[j] == tape[k].new_var); } if( match ) match_var = i_var; } return match_var; } /*! Record an operation of the form (parameter op variable). \param tape is a vector that maps a variable index, in the old operation sequence, to an struct_old_variable information record. Note that the index for this vector must be greater than or equal zero and less than tape.size(). \li tape[i].op is the operator in the old operation sequence corresponding to the old variable index \c i. Assertion: NumRes(tape[i].op) > 0. \li tape[i].arg for j < NumArg( tape[i].op ), tape[i].arg[j] is the j-th the argument, in the old operation sequence, corresponding to the old variable index \c i. Assertion: tape[i].arg[j] < i. \li tape[i].new_var Suppose i <= current, j < NumArg( tape[i].op ), and k = tape[i].arg[j], and \c j corresponds to a variable for operator tape[i].op. It follows that tape[k].new_var has alread been set to the variable in the new operation sequence corresponding to the old variable index \c k. This means that the \c new_var value has been set for all the possible arguments that come before \a current. \param current is the index in the old operation sequence for the variable corresponding to the result for the current operator. Assertions: current < tape.size(), NumRes( tape[current].op ) > 0. \param npar is the number of parameters corresponding to this operation sequence. \param par is a vector of length \a npar containing the parameters for this operation sequence; i.e., given a parameter index \c i, the corresponding parameter value is par[i]. \param rec is the object that will record the operations. \param op is the operator that we are recording which must be one of the following: AddpvOp, DivpvOp, MulpvOp, PowvpOp, SubpvOp. \param arg is the vector of arguments for this operator. \return the result is the operaiton and variable index corresponding to the current operation in the new operation sequence. */ template struct_size_pair record_pv( const CppAD::vector& tape , size_t current , size_t npar , const Base* par , recorder* rec , OpCode op , const addr_t* arg ) { # ifndef NDEBUG switch(op) { case AddpvOp: case DivpvOp: case MulpvOp: case PowpvOp: case SubpvOp: break; default: CPPAD_ASSERT_UNKNOWN(false); } # endif CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < npar ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current ); addr_t new_arg[2]; new_arg[0] = rec->PutPar( par[arg[0]] ); new_arg[1] = tape[ arg[1] ].new_var; rec->PutArg( new_arg[0], new_arg[1] ); struct_size_pair ret; ret.i_op = rec->num_op_rec(); ret.i_var = rec->PutOp(op); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < ret.i_var ); return ret; } /*! Record an operation of the form (variable op parameter). \param tape is a vector that maps a variable index, in the old operation sequence, to an struct_old_variable information record. Note that the index for this vector must be greater than or equal zero and less than tape.size(). \li tape[i].op is the operator in the old operation sequence corresponding to the old variable index \c i. Assertion: NumRes(tape[i].op) > 0. \li tape[i].arg for j < NumArg( tape[i].op ), tape[i].arg[j] is the j-th the argument, in the old operation sequence, corresponding to the old variable index \c i. Assertion: tape[i].arg[j] < i. \li tape[i].new_var Suppose i <= current, j < NumArg( tape[i].op ), and k = tape[i].arg[j], and \c j corresponds to a variable for operator tape[i].op. It follows that tape[k].new_var has alread been set to the variable in the new operation sequence corresponding to the old variable index \c k. This means that the \c new_var value has been set for all the possible arguments that come before \a current. \param current is the index in the old operation sequence for the variable corresponding to the result for the current operator. Assertions: current < tape.size(), NumRes( tape[current].op ) > 0. \param npar is the number of parameters corresponding to this operation sequence. \param par is a vector of length \a npar containing the parameters for this operation sequence; i.e., given a parameter index \c i, the corresponding parameter value is par[i]. \param rec is the object that will record the operations. \param op is the operator that we are recording which must be one of the following: DivvpOp, PowvpOp, SubvpOp. \param arg is the vector of arguments for this operator. \return the result operation and variable index corresponding to the current operation in the new operation sequence. */ template struct_size_pair record_vp( const CppAD::vector& tape , size_t current , size_t npar , const Base* par , recorder* rec , OpCode op , const addr_t* arg ) { # ifndef NDEBUG switch(op) { case DivvpOp: case PowvpOp: case SubvpOp: break; default: CPPAD_ASSERT_UNKNOWN(false); } # endif CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < current ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < npar ); addr_t new_arg[2]; new_arg[0] = tape[ arg[0] ].new_var; new_arg[1] = rec->PutPar( par[arg[1]] ); rec->PutArg( new_arg[0], new_arg[1] ); struct_size_pair ret; ret.i_op = rec->num_op_rec(); ret.i_var = rec->PutOp(op); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < ret.i_var ); return ret; } /*! Record an operation of the form (variable op variable). \param tape is a vector that maps a variable index, in the old operation sequence, to an struct_old_variable information record. Note that the index for this vector must be greater than or equal zero and less than tape.size(). \li tape[i].op is the operator in the old operation sequence corresponding to the old variable index \c i. Assertion: NumRes(tape[i].op) > 0. \li tape[i].arg for j < NumArg( tape[i].op ), tape[i].arg[j] is the j-th the argument, in the old operation sequence, corresponding to the old variable index \c i. Assertion: tape[i].arg[j] < i. \li tape[i].new_var Suppose i <= current, j < NumArg( tape[i].op ), and k = tape[i].arg[j], and \c j corresponds to a variable for operator tape[i].op. It follows that tape[k].new_var has alread been set to the variable in the new operation sequence corresponding to the old variable index \c k. This means that the \c new_var value has been set for all the possible arguments that come before \a current. \param current is the index in the old operation sequence for the variable corresponding to the result for the current operator. Assertions: current < tape.size(), NumRes( tape[current].op ) > 0. \param npar is the number of parameters corresponding to this operation sequence. \param par is a vector of length \a npar containing the parameters for this operation sequence; i.e., given a parameter index \c i, the corresponding parameter value is par[i]. \param rec is the object that will record the operations. \param op is the operator that we are recording which must be one of the following: AddvvOp, DivvvOp, MulvvOp, PowvpOp, SubvvOp. \param arg is the vector of arguments for this operator. \return the result is the operation and variable index corresponding to the current operation in the new operation sequence. */ template struct_size_pair record_vv( const CppAD::vector& tape , size_t current , size_t npar , const Base* par , recorder* rec , OpCode op , const addr_t* arg ) { # ifndef NDEBUG switch(op) { case AddvvOp: case DivvvOp: case MulvvOp: case PowvvOp: case SubvvOp: break; default: CPPAD_ASSERT_UNKNOWN(false); } # endif CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < current ); CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current ); addr_t new_arg[2]; new_arg[0] = tape[ arg[0] ].new_var; new_arg[1] = tape[ arg[1] ].new_var; rec->PutArg( new_arg[0], new_arg[1] ); struct_size_pair ret; ret.i_op = rec->num_op_rec(); ret.i_var = rec->PutOp(op); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < ret.i_var ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < ret.i_var ); return ret; } // ========================================================================== /*! Recording a cummulative cummulative summation starting at its highest parrent. \param tape is a vector that maps a variable index, in the old operation sequence, to an struct_old_variable information record. Note that the index for this vector must be greater than or equal zero and less than tape.size(). \li tape[i].op is the operator in the old operation sequence corresponding to the old variable index \c i. Assertion: NumRes(tape[i].op) > 0. \li tape[i].arg for j < NumArg( tape[i].op ), tape[i].arg[j] is the j-th the argument, in the old operation sequence, corresponding to the old variable index \c i. Assertion: tape[i].arg[j] < i. \li tape[i].new_var Suppose i <= current, j < NumArg( tape[i].op ), and k = tape[i].arg[j], and \c j corresponds to a variable for operator tape[i].op. It follows that tape[k].new_var has alread been set to the variable in the new operation sequence corresponding to the old variable index \c k. This means that the \c new_var value has been set for all the possible arguments that come before \a current. \param current is the index in the old operation sequence for the variable corresponding to the result for the current operator. Assertions: current < tape.size(), NumRes( tape[current].op ) > 0. \param npar is the number of parameters corresponding to this operation sequence. \param par is a vector of length \a npar containing the parameters for this operation sequence; i.e., given a parameter index \c i, the corresponding parameter value is par[i]. \param rec is the object that will record the operations. \param work Is used for computation. On input and output, work.op_stack.empty(), work.add_stack.empty(), and work.sub_stack.empty(), are all true true. These stacks are passed in so that elements can be allocated once and then the elements can be reused with calls to \c record_csum. \par Exception tape[i].new_var is not yet defined for any node \c i that is \c csum_connected to the \a current node (or that is \c sum_connected to a node that is \c csum_connected). For example; suppose that index \c j corresponds to a variable in the current operator, i = tape[current].arg[j], and tape[arg[j]].connect_type == csum_connected. It then follows that tape[i].new_var == tape.size(). \par Restriction: \li tape[current].op must be one of AddpvOp, AddvvOp, SubpvOp, SubvpOp, SubvvOp. \li tape[current].connect_type must be \c yes_connected. \li tape[j].connect_type == csum_connected for some index j that is a variable operand for the current operation. */ template struct_size_pair record_csum( const CppAD::vector& tape , size_t current , size_t npar , const Base* par , recorder* rec , struct_csum_stacks& work ) { CPPAD_ASSERT_UNKNOWN( work.op_stack.empty() ); CPPAD_ASSERT_UNKNOWN( work.add_stack.empty() ); CPPAD_ASSERT_UNKNOWN( work.sub_stack.empty() ); CPPAD_ASSERT_UNKNOWN( tape[current].connect_type == yes_connected ); size_t i; OpCode op; const addr_t* arg; bool add; struct struct_csum_variable var; var.op = tape[current].op; var.arg = tape[current].arg; var.add = true; work.op_stack.push( var ); Base sum_par(0); # ifndef NDEBUG bool ok = false; if( var.op == SubvpOp ) ok = tape[ tape[current].arg[0] ].connect_type == csum_connected; if( var.op == AddpvOp || var.op == SubpvOp ) ok = tape[ tape[current].arg[1] ].connect_type == csum_connected; if( var.op == AddvvOp || var.op == SubvvOp ) { ok = tape[ tape[current].arg[0] ].connect_type == csum_connected; ok |= tape[ tape[current].arg[1] ].connect_type == csum_connected; } CPPAD_ASSERT_UNKNOWN( ok ); # endif while( ! work.op_stack.empty() ) { var = work.op_stack.top(); work.op_stack.pop(); op = var.op; arg = var.arg; add = var.add; // process first argument to this operator switch(op) { case AddpvOp: case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < npar ); if( add ) sum_par += par[arg[0]]; else sum_par -= par[arg[0]]; break; case AddvvOp: case SubvpOp: case SubvvOp: if( tape[arg[0]].connect_type == csum_connected ) { CPPAD_ASSERT_UNKNOWN( size_t(tape[arg[0]].new_var) == tape.size() ); var.op = tape[arg[0]].op; var.arg = tape[arg[0]].arg; var.add = add; work.op_stack.push( var ); } else if( add ) work.add_stack.push(arg[0]); else work.sub_stack.push(arg[0]); break; default: CPPAD_ASSERT_UNKNOWN(false); } // process second argument to this operator switch(op) { case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < npar ); if( add ) sum_par -= par[arg[1]]; else sum_par += par[arg[1]]; break; case SubvvOp: case SubpvOp: add = ! add; case AddvvOp: case AddpvOp: if( tape[arg[1]].connect_type == csum_connected ) { CPPAD_ASSERT_UNKNOWN( size_t(tape[arg[1]].new_var) == tape.size() ); var.op = tape[arg[1]].op; var.arg = tape[arg[1]].arg; var.add = add; work.op_stack.push( var ); } else if( add ) work.add_stack.push(arg[1]); else work.sub_stack.push(arg[1]); break; default: CPPAD_ASSERT_UNKNOWN(false); } } // number of variables in this cummulative sum operator size_t n_add = work.add_stack.size(); size_t n_sub = work.sub_stack.size(); size_t old_arg, new_arg; rec->PutArg(n_add); // arg[0] rec->PutArg(n_sub); // arg[1] new_arg = rec->PutPar( sum_par ); rec->PutArg(new_arg); // arg[2] for(i = 0; i < n_add; i++) { CPPAD_ASSERT_UNKNOWN( ! work.add_stack.empty() ); old_arg = work.add_stack.top(); new_arg = tape[old_arg].new_var; CPPAD_ASSERT_UNKNOWN( new_arg < tape.size() ); rec->PutArg(new_arg); // arg[3+i] work.add_stack.pop(); } for(i = 0; i < n_sub; i++) { CPPAD_ASSERT_UNKNOWN( ! work.sub_stack.empty() ); old_arg = work.sub_stack.top(); new_arg = tape[old_arg].new_var; CPPAD_ASSERT_UNKNOWN( new_arg < tape.size() ); rec->PutArg(new_arg); // arg[3 + arg[0] + i] work.sub_stack.pop(); } rec->PutArg(n_add + n_sub); // arg[3 + arg[0] + arg[1]] struct_size_pair ret; ret.i_op = rec->num_op_rec(); ret.i_var = rec->PutOp(CSumOp); CPPAD_ASSERT_UNKNOWN( new_arg < ret.i_var ); return ret; } // ========================================================================== /*! Convert a player object to an optimized recorder object \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param options The possible values for this string are: "", "no_conditional_skip". If it is "no_conditional_skip", then no conditional skip operations will be generated. \param n is the number of independent variables on the tape. \param dep_taddr On input this vector contains the indices for each of the dependent variable values in the operation sequence corresponding to \a play. Upon return it contains the indices for the same variables but in the operation sequence corresponding to \a rec. \param play This is the operation sequence that we are optimizing. It is essentially const, except for play back state which changes while it plays back the operation seqeunce. \param rec The input contents of this recording does not matter. Upon return, it contains an optimized verison of the operation sequence corresponding to \a play. */ template void optimize_run( const std::string& options , size_t n , CppAD::vector& dep_taddr , player* play , recorder* rec ) { // temporary indices size_t i, j, k; // check options bool conditional_skip = options.find("no_conditional_skip", 0) == std::string::npos; // temporary variables OpCode op; // current operator const addr_t* arg; // operator arguments size_t i_var; // index of first result for current operator // range and domain dimensions for F size_t m = dep_taddr.size(); // number of variables in the player const size_t num_var = play->num_var_rec(); # ifndef NDEBUG // number of parameters in the player const size_t num_par = play->num_par_rec(); # endif // number of VecAD indices size_t num_vecad_ind = play->num_vec_ind_rec(); // number of VecAD vectors size_t num_vecad_vec = play->num_vecad_vec_rec(); // ------------------------------------------------------------- // data structure that maps variable index in original operation // sequence to corresponding operator information CppAD::vector tape(num_var); // if tape[i].connect_type == exp_connected, cexp_set[i] is the // corresponding information for the conditional connection. CppAD::vector cexp_vec_set; if( conditional_skip ) cexp_vec_set.resize(num_var); // ------------------------------------------------------------- // Determine how each variable is connected to the dependent variables // initialize all variables has having no connections for(i = 0; i < num_var; i++) tape[i].connect_type = not_connected; for(j = 0; j < m; j++) { // mark dependent variables as having one or more connections tape[ dep_taddr[j] ].connect_type = yes_connected; } // vecad_connect contains a value for each VecAD object. // vecad maps a VecAD index (which corresponds to the beginning of the // VecAD object) to the vecad_connect falg for the VecAD object. CppAD::vector vecad_connect(num_vecad_vec); CppAD::vector vecad(num_vecad_ind); j = 0; for(i = 0; i < num_vecad_vec; i++) { vecad_connect[i] = not_connected; // length of this VecAD size_t length = play->GetVecInd(j); // set to proper index for this VecAD vecad[j] = i; for(k = 1; k <= length; k++) vecad[j+k] = num_vecad_vec; // invalid index // start of next VecAD j += length + 1; } CPPAD_ASSERT_UNKNOWN( j == num_vecad_ind ); // work space used by UserOp. typedef std::set size_set; vector user_r_set; // set sparsity pattern for result vector user_s_set; // set sparisty pattern for argument vector user_r_bool; // bool sparsity pattern for result vector user_s_bool; // bool sparisty pattern for argument // size_t user_q = 0; // column dimension for sparsity patterns size_t user_index = 0; // indentifier for this user_atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base* user_atom = CPPAD_NULL; // current user atomic function bool user_set = true; // use set sparsity (or bool) // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state; // During reverse mode, compute type of connection for each call to // a user atomic function. CppAD::vector user_info; size_t user_curr = 0; /// During reverse mode, information for each CSkip operation CppAD::vector cskip_info; // Initialize a reverse mode sweep through the operation sequence size_t i_op; play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); size_t mask; user_state = user_end; while(op != BeginOp) { // next op play->reverse_next(op, arg, i_op, i_var); // Store the operator corresponding to each variable if( NumRes(op) > 0 ) { tape[i_var].op = op; tape[i_var].arg = arg; } # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif enum_connect_type connect_type = tape[i_var].connect_type; class_set_cexp_pair* cexp_set = CPPAD_NULL; if( conditional_skip ) cexp_set = &cexp_vec_set[i_var]; switch( op ) { // One variable corresponding to arg[0] case AbsOp: case AcosOp: case AsinOp: case AtanOp: case CosOp: case CoshOp: case DivvpOp: case ErfOp: case ExpOp: case LogOp: case PowvpOp: case SignOp: case SinOp: case SinhOp: case SqrtOp: case TanOp: case TanhOp: switch( connect_type ) { case not_connected: break; case yes_connected: case sum_connected: case csum_connected: tape[arg[0]].connect_type = yes_connected; break; case cexp_connected: CPPAD_ASSERT_UNKNOWN( conditional_skip ) if( tape[arg[0]].connect_type == not_connected ) { tape[arg[0]].connect_type = cexp_connected; cexp_vec_set[arg[0]] = *cexp_set; } else if( tape[arg[0]].connect_type == cexp_connected ) { cexp_vec_set[arg[0]].intersection(*cexp_set); if( cexp_vec_set[arg[0]].empty() ) tape[arg[0]].connect_type = yes_connected; } else tape[arg[0]].connect_type = yes_connected; break; default: CPPAD_ASSERT_UNKNOWN(false); } break; // -------------------------------------------- // One variable corresponding to arg[1] case DisOp: case DivpvOp: case MulpvOp: case PowpvOp: switch( connect_type ) { case not_connected: break; case yes_connected: case sum_connected: case csum_connected: tape[arg[1]].connect_type = yes_connected; break; case cexp_connected: CPPAD_ASSERT_UNKNOWN( conditional_skip ) if( tape[arg[1]].connect_type == not_connected ) { tape[arg[1]].connect_type = cexp_connected; cexp_vec_set[arg[1]] = *cexp_set; } else if( tape[arg[1]].connect_type == cexp_connected ) { cexp_vec_set[arg[1]].intersection(*cexp_set); if( cexp_vec_set[arg[1]].empty() ) tape[arg[1]].connect_type = yes_connected; } else tape[arg[1]].connect_type = yes_connected; break; default: CPPAD_ASSERT_UNKNOWN(false); } break; // -------------------------------------------- // Special case for SubvpOp case SubvpOp: switch( connect_type ) { case not_connected: break; case yes_connected: case sum_connected: case csum_connected: if( tape[arg[0]].connect_type == not_connected ) tape[arg[0]].connect_type = sum_connected; else tape[arg[0]].connect_type = yes_connected; break; case cexp_connected: CPPAD_ASSERT_UNKNOWN( conditional_skip ) if( tape[arg[0]].connect_type == not_connected ) { tape[arg[0]].connect_type = cexp_connected; cexp_vec_set[arg[0]] = *cexp_set; } else if( tape[arg[0]].connect_type == cexp_connected ) { cexp_vec_set[arg[0]].intersection(*cexp_set); if( cexp_vec_set[arg[0]].empty() ) tape[arg[0]].connect_type = yes_connected; } else tape[arg[0]].connect_type = yes_connected; break; default: CPPAD_ASSERT_UNKNOWN(false); } if( connect_type == sum_connected ) { // convert sum to csum connection for this variable tape[i_var].connect_type = connect_type = csum_connected; } break; // -------------------------------------------- // Special case for AddpvOp and SubpvOp case AddpvOp: case SubpvOp: switch( connect_type ) { case not_connected: break; case yes_connected: case sum_connected: case csum_connected: if( tape[arg[1]].connect_type == not_connected ) tape[arg[1]].connect_type = sum_connected; else tape[arg[1]].connect_type = yes_connected; break; case cexp_connected: CPPAD_ASSERT_UNKNOWN( conditional_skip ) if( tape[arg[1]].connect_type == not_connected ) { tape[arg[1]].connect_type = cexp_connected; cexp_vec_set[arg[1]] = *cexp_set; } else if( tape[arg[1]].connect_type == cexp_connected ) { cexp_vec_set[arg[1]].intersection(*cexp_set); if( cexp_vec_set[arg[1]].empty() ) tape[arg[1]].connect_type = yes_connected; } else tape[arg[1]].connect_type = yes_connected; break; default: CPPAD_ASSERT_UNKNOWN(false); } if( connect_type == sum_connected ) { // convert sum to csum connection for this variable tape[i_var].connect_type = connect_type = csum_connected; } break; // -------------------------------------------- // Special case for AddvvOp and SubvvOp case AddvvOp: case SubvvOp: for(i = 0; i < 2; i++) switch( connect_type ) { case not_connected: break; case yes_connected: case sum_connected: case csum_connected: if( tape[arg[i]].connect_type == not_connected ) tape[arg[i]].connect_type = sum_connected; else tape[arg[i]].connect_type = yes_connected; break; case cexp_connected: CPPAD_ASSERT_UNKNOWN( conditional_skip ) if( tape[arg[i]].connect_type == not_connected ) { tape[arg[i]].connect_type = cexp_connected; cexp_vec_set[arg[i]] = *cexp_set; } else if( tape[arg[i]].connect_type == cexp_connected ) { cexp_vec_set[arg[i]].intersection(*cexp_set); if( cexp_vec_set[arg[i]].empty() ) tape[arg[i]].connect_type = yes_connected; } else tape[arg[i]].connect_type = yes_connected; break; default: CPPAD_ASSERT_UNKNOWN(false); } if( connect_type == sum_connected ) { // convert sum to csum connection for this variable tape[i_var].connect_type = connect_type = csum_connected; } break; // -------------------------------------------- // Other binary operators // where operands are arg[0], arg[1] case DivvvOp: case MulvvOp: case PowvvOp: for(i = 0; i < 2; i++) switch( connect_type ) { case not_connected: break; case yes_connected: case sum_connected: case csum_connected: tape[arg[i]].connect_type = yes_connected; break; case cexp_connected: CPPAD_ASSERT_UNKNOWN( conditional_skip ) if( tape[arg[i]].connect_type == not_connected ) { tape[arg[i]].connect_type = cexp_connected; cexp_vec_set[arg[i]] = *cexp_set; } else if( tape[arg[i]].connect_type == cexp_connected ) { cexp_vec_set[arg[i]].intersection(*cexp_set); if( cexp_vec_set[arg[i]].empty() ) tape[arg[i]].connect_type = yes_connected; } else tape[arg[i]].connect_type = yes_connected; break; default: CPPAD_ASSERT_UNKNOWN(false); } break; // -------------------------------------------- // Conditional expression operators case CExpOp: CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); if( connect_type != not_connected ) { struct_cskip_info info; info.cop = CompareOp( arg[0] ); info.flag = arg[1]; info.left = arg[2]; info.right = arg[3]; info.n_op_true = 0; info.n_op_false = 0; info.i_arg = 0; // case where no CSkipOp for this CExpOp // size_t index = 0; if( arg[1] & 1 ) { index = std::max(index, info.left); tape[info.left].connect_type = yes_connected; } if( arg[1] & 2 ) { index = std::max(index, info.right); tape[info.right].connect_type = yes_connected; } CPPAD_ASSERT_UNKNOWN( index > 0 ); info.max_left_right = index; // index = cskip_info.size(); cskip_info.push_back(info); // if( arg[1] & 4 ) { if( conditional_skip && tape[arg[4]].connect_type == not_connected ) { tape[arg[4]].connect_type = cexp_connected; cexp_vec_set[arg[4]] = *cexp_set; cexp_vec_set[arg[4]].insert( class_cexp_pair(true, index) ); } else { // if arg[4] is cexp_connected, it could be // connected for both the true and false case // 2DO: if previously cexp_connected // and the true/false sense is the same, should // keep this conditional connnection. if(conditional_skip) cexp_vec_set[arg[4]].clear(); tape[arg[4]].connect_type = yes_connected; } } if( arg[1] & 8 ) { if( conditional_skip && tape[arg[5]].connect_type == not_connected ) { tape[arg[5]].connect_type = cexp_connected; cexp_vec_set[arg[5]] = *cexp_set; cexp_vec_set[arg[5]].insert( class_cexp_pair(false, index) ); } else { if(conditional_skip) cexp_vec_set[arg[5]].clear(); tape[arg[5]].connect_type = yes_connected; } } } break; // -------------------------------------------- // Operations where there is nothing to do case EndOp: case ParOp: case PriOp: break; // -------------------------------------------- // Operators that never get removed case BeginOp: case InvOp: tape[i_var].connect_type = yes_connected; break; // Compare operators never get removed ----------------- case LepvOp: case LtpvOp: case EqpvOp: case NepvOp: tape[arg[1]].connect_type = yes_connected; break; case LevpOp: case LtvpOp: tape[arg[0]].connect_type = yes_connected; break; case LevvOp: case LtvvOp: case EqvvOp: case NevvOp: tape[arg[0]].connect_type = yes_connected; tape[arg[1]].connect_type = yes_connected; break; // Load using a parameter index ---------------------- case LdpOp: if( tape[i_var].connect_type != not_connected ) { i = vecad[ arg[0] - 1 ]; vecad_connect[i] = yes_connected; } break; // -------------------------------------------- // Load using a variable index case LdvOp: if( tape[i_var].connect_type != not_connected ) { i = vecad[ arg[0] - 1 ]; vecad_connect[i] = yes_connected; tape[arg[1]].connect_type = yes_connected; } break; // -------------------------------------------- // Store a variable using a parameter index case StpvOp: i = vecad[ arg[0] - 1 ]; if( vecad_connect[i] != not_connected ) tape[arg[2]].connect_type = yes_connected; break; // -------------------------------------------- // Store a variable using a variable index case StvvOp: i = vecad[ arg[0] - 1 ]; if( vecad_connect[i] ) { tape[arg[1]].connect_type = yes_connected; tape[arg[2]].connect_type = yes_connected; } break; // ============================================================ case UserOp: // start or end atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_end ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_q = 1; user_atom = atomic_base::class_object(user_index); user_set = user_atom->sparsity() == atomic_base::set_sparsity_enum; // if(user_s_set.size() != user_n ) user_s_set.resize(user_n); if(user_r_set.size() != user_m ) user_r_set.resize(user_m); // // Note user_q is 1, but use it for clarity of code if(user_s_bool.size() != user_n * user_q ) user_s_bool.resize(user_n * user_q); if(user_r_bool.size() != user_m * user_q ) user_r_bool.resize(user_m * user_q); // user_j = user_n; user_i = user_m; user_state = user_ret; // struct_user_info info; info.connect_type = not_connected; info.op_end = i_op + 1; user_info.push_back(info); } else { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); user_state = user_end; // CPPAD_ASSERT_UNKNOWN( user_curr + 1 == user_info.size() ); user_info[user_curr].op_begin = i_op; user_curr = user_info.size(); } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_j; if( user_j == 0 ) user_state = user_start; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); --user_j; if( user_set ) { if( ! user_s_set[user_j].empty() ) tape[arg[0]].connect_type = user_info[user_curr].connect_type; } else { if( user_s_bool[user_j] ) tape[arg[0]].connect_type = user_info[user_curr].connect_type; } if( user_j == 0 ) user_state = user_start; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); --user_i; user_r_set[user_i].clear(); user_r_bool[user_i] = false; switch( connect_type ) { case not_connected: break; case yes_connected: case sum_connected: case csum_connected: user_info[user_curr].connect_type = yes_connected; user_r_set[user_i].insert(0); user_r_bool[user_i] = true; break; case cexp_connected: CPPAD_ASSERT_UNKNOWN( conditional_skip ); if( user_info[user_curr].connect_type == not_connected ) { user_info[user_curr].connect_type = connect_type; user_info[user_curr].cexp_set = *cexp_set; } else if(user_info[user_curr].connect_type==cexp_connected) { user_info[user_curr].cexp_set.intersection(*cexp_set); if( user_info[user_curr].cexp_set.empty() ) user_info[user_curr].connect_type = yes_connected; } else user_info[user_curr].connect_type = yes_connected; user_r_set[user_i].insert(0); user_r_bool[user_i] = true; break; default: CPPAD_ASSERT_UNKNOWN(false); } // drop into op = UsrrpOp code to handle case where user_i == 0 // for both UsrrvOp and UsrrpOp together. case UsrrpOp: if( op == UsrrpOp ) { // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_i; user_r_set[user_i].clear(); user_r_bool[user_i] = false; } if( user_i == 0 ) { // call users function for this operation user_atom->set_id(user_id); # ifdef NDEBUG if( user_set ) { user_atom-> rev_sparse_jac(user_q, user_r_set, user_s_set); } else { user_atom-> rev_sparse_jac(user_q, user_r_bool, user_s_bool); } # else bool flag; if( user_set ) { flag = user_atom-> rev_sparse_jac(user_q, user_r_set, user_s_set); } else { flag = user_atom-> rev_sparse_jac(user_q, user_r_bool, user_s_bool); } if( ! flag ) { std::string s = "Optimizing an ADFun object" " that contains the atomic function\n\t"; s += user_atom->afun_name(); s += "\nCurrent atomic_sparsity is set to"; // if( user_set ) s += " std::set\nand std::set"; else s += " bool\nand bool"; // s += " version of rev_sparse_jac returned false"; CPPAD_ASSERT_KNOWN(false, s.c_str() ); } # endif user_state = user_arg; } break; // ============================================================ // all cases should be handled above default: CPPAD_ASSERT_UNKNOWN(0); } } // values corresponding to BeginOp CPPAD_ASSERT_UNKNOWN( i_op == 0 && i_var == 0 && op == BeginOp ); tape[i_var].op = op; tape[i_var].connect_type = yes_connected; // ------------------------------------------------------------- // Determine which variables can be conditionally skipped for(i = 0; i < num_var; i++) { if( tape[i].connect_type == cexp_connected && ! cexp_vec_set[i].empty() ) { std::set::const_iterator itr = cexp_vec_set[i].begin(); while( itr != cexp_vec_set[i].end() ) { j = itr->index(); if( itr->compare() == true ) cskip_info[j].skip_var_false.push_back(i); else cskip_info[j].skip_var_true.push_back(i); itr++; } } } // Determine size of skip information in user_info for(i = 0; i < user_info.size(); i++) { if( user_info[i].connect_type == cexp_connected && ! user_info[i].cexp_set.empty() ) { std::set::const_iterator itr = user_info[i].cexp_set.begin(); while( itr != user_info[i].cexp_set.end() ) { j = itr->index(); if( itr->compare() == true ) cskip_info[j].n_op_false = user_info[i].op_end - user_info[i].op_begin; else cskip_info[j].n_op_true = user_info[i].op_end - user_info[i].op_begin; itr++; } } } // Sort the conditional skip information by the maximum of the // index for the left and right comparision operands CppAD::vector cskip_info_order( cskip_info.size() ); { CppAD::vector keys( cskip_info.size() ); for(i = 0; i < cskip_info.size(); i++) keys[i] = std::max( cskip_info[i].left, cskip_info[i].right ); CppAD::index_sort(keys, cskip_info_order); } // index in sorted order size_t cskip_order_next = 0; // index in order during reverse sweep size_t cskip_info_index = cskip_info.size(); // Initilaize table mapping hash code to variable index in tape // as pointing to the BeginOp at the beginning of the tape CppAD::vector hash_table_var(CPPAD_HASH_TABLE_SIZE); for(i = 0; i < CPPAD_HASH_TABLE_SIZE; i++) hash_table_var[i] = 0; CPPAD_ASSERT_UNKNOWN( tape[0].op == BeginOp ); // initialize mapping from old variable index to new // operator and variable index for(i = 0; i < num_var; i++) { tape[i].new_op = 0; // invalid index (except for BeginOp) tape[i].new_var = num_var; // invalid index } // Erase all information in the old recording rec->free(); // initialize mapping from old VecAD index to new VecAD index CppAD::vector new_vecad_ind(num_vecad_ind); for(i = 0; i < num_vecad_ind; i++) new_vecad_ind[i] = num_vecad_ind; // invalid index j = 0; // index into the old set of indices for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD size_t length = play->GetVecInd(j); if( vecad_connect[i] != not_connected ) { // Put this VecAD vector in new recording CPPAD_ASSERT_UNKNOWN(length < num_vecad_ind); new_vecad_ind[j] = rec->PutVecInd(length); for(k = 1; k <= length; k++) new_vecad_ind[j+k] = rec->PutVecInd( rec->PutPar( play->GetPar( play->GetVecInd(j+k) ) ) ); } // start of next VecAD j += length + 1; } CPPAD_ASSERT_UNKNOWN( j == num_vecad_ind ); // start playing the operations in the forward direction play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( user_curr == user_info.size() ); // playing forward skips BeginOp at the beginning, but not EndOp at // the end. Put BeginOp at beginning of recording CPPAD_ASSERT_UNKNOWN( op == BeginOp ); CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1); tape[i_var].new_op = rec->num_op_rec(); tape[i_var].new_var = rec->PutOp(BeginOp); rec->PutArg(0); // temporary buffer for new argument values addr_t new_arg[6]; // temporary work space used by record_csum // (decalared here to avoid realloaction of memory) struct_csum_stacks csum_work; // tempory used to hold a size_pair struct_size_pair size_pair; user_state = user_start; while(op != EndOp) { // next op play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); // determine if we should insert a conditional skip here bool skip = cskip_order_next < cskip_info.size(); skip &= op != BeginOp; skip &= op != InvOp; skip &= user_state == user_start; if( skip ) { j = cskip_info_order[cskip_order_next]; if( NumRes(op) > 0 ) skip &= cskip_info[j].max_left_right < i_var; else skip &= cskip_info[j].max_left_right <= i_var; } if( skip ) { cskip_order_next++; struct_cskip_info info = cskip_info[j]; size_t n_true = info.skip_var_true.size() + info.n_op_true; size_t n_false = info.skip_var_false.size() + info.n_op_false; skip &= n_true > 0 || n_false > 0; if( skip ) { CPPAD_ASSERT_UNKNOWN( NumRes(CSkipOp) == 0 ); size_t n_arg = 7 + n_true + n_false; // reserve space for the arguments to this operator but // delay setting them until we have all the new addresses cskip_info[j].i_arg = rec->ReserveArg(n_arg); CPPAD_ASSERT_UNKNOWN( cskip_info[j].i_arg > 0 ); rec->PutOp(CSkipOp); } } // determine if we should keep this operation in the new // operation sequence bool keep; switch( op ) { // see wish_list/Optimize/CompareChange entry. case EqpvOp: case EqvvOp: case LepvOp: case LevpOp: case LevvOp: case LtpvOp: case LtvpOp: case LtvvOp: case NepvOp: case NevvOp: keep = true; break; case PriOp: keep = false; break; case InvOp: case EndOp: keep = true; break; case StppOp: case StvpOp: case StpvOp: case StvvOp: CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 ); i = vecad[ arg[0] - 1 ]; keep = vecad_connect[i] != not_connected; break; case AddpvOp: case AddvvOp: case SubpvOp: case SubvpOp: case SubvvOp: keep = tape[i_var].connect_type != not_connected; keep &= tape[i_var].connect_type != csum_connected; break; case UserOp: case UsrapOp: case UsravOp: case UsrrpOp: case UsrrvOp: keep = true; break; default: keep = tape[i_var].connect_type != not_connected; break; } unsigned short code = 0; bool replace_hash = false; addr_t match_var; tape[i_var].match = false; if( keep ) switch( op ) { // Unary operator where operand is arg[0] case AbsOp: case AcosOp: case AsinOp: case AtanOp: case CosOp: case CoshOp: case ErfOp: case ExpOp: case LogOp: case SignOp: case SinOp: case SinhOp: case SqrtOp: case TanOp: case TanhOp: match_var = unary_match( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , hash_table_var , code // outputs ); if( match_var > 0 ) { tape[i_var].match = true; tape[match_var].match = true; tape[i_var].new_var = tape[match_var].new_var; } else { replace_hash = true; new_arg[0] = tape[ arg[0] ].new_var; rec->PutArg( new_arg[0] ); tape[i_var].new_op = rec->num_op_rec(); tape[i_var].new_var = i = rec->PutOp(op); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < i ); if( op == ErfOp ) { // Error function is a special case // second argument is always the parameter 0 // third argument is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 ); rec->PutArg( rec->PutPar( Base(0) ) ); rec->PutArg( rec->PutPar( Base( 1.0 / std::sqrt( std::atan(1.0) ) ) ) ); } } break; // --------------------------------------------------- // Binary operators where // left is a variable and right is a parameter case SubvpOp: if( tape[arg[0]].connect_type == csum_connected ) { // convert to a sequence of summation operators size_pair = record_csum( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , rec , csum_work ); tape[i_var].new_op = size_pair.i_op; tape[i_var].new_var = size_pair.i_var; // abort rest of this case break; } case DivvpOp: case PowvpOp: match_var = binary_match( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , hash_table_var , code // outputs ); if( match_var > 0 ) { tape[i_var].match = true; tape[match_var].match = true; tape[i_var].new_var = tape[match_var].new_var; } else { size_pair = record_vp( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , rec , op , arg ); tape[i_var].new_op = size_pair.i_op; tape[i_var].new_var = size_pair.i_var; replace_hash = true; } break; // --------------------------------------------------- // Binary operators where // left is an index and right is a variable case DisOp: match_var = binary_match( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , hash_table_var , code // outputs ); if( match_var > 0 ) { tape[i_var].match = true; tape[match_var].match = true; tape[i_var].new_var = tape[match_var].new_var; } else { new_arg[0] = arg[0]; new_arg[1] = tape[ arg[1] ].new_var; rec->PutArg( new_arg[0], new_arg[1] ); tape[i_var].new_op = rec->num_op_rec(); tape[i_var].new_var = rec->PutOp(op); CPPAD_ASSERT_UNKNOWN( new_arg[1] < tape[i_var].new_var ); replace_hash = true; } break; // --------------------------------------------------- // Binary operators where // left is a parameter and right is a variable case SubpvOp: case AddpvOp: if( tape[arg[1]].connect_type == csum_connected ) { // convert to a sequence of summation operators size_pair = record_csum( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , rec , csum_work ); tape[i_var].new_op = size_pair.i_op; tape[i_var].new_var = size_pair.i_var; // abort rest of this case break; } case DivpvOp: case MulpvOp: case PowpvOp: match_var = binary_match( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , hash_table_var , code // outputs ); if( match_var > 0 ) { tape[i_var].match = true; tape[match_var].match = true; tape[i_var].new_var = tape[match_var].new_var; } else { size_pair = record_pv( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , rec , op , arg ); tape[i_var].new_op = size_pair.i_op; tape[i_var].new_var = size_pair.i_var; replace_hash = true; } break; // --------------------------------------------------- // Binary operator where // both operators are variables case AddvvOp: case SubvvOp: if( (tape[arg[0]].connect_type == csum_connected) || (tape[arg[1]].connect_type == csum_connected) ) { // convert to a sequence of summation operators size_pair = record_csum( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , rec , csum_work ); tape[i_var].new_op = size_pair.i_op; tape[i_var].new_var = size_pair.i_var; // abort rest of this case break; } case DivvvOp: case MulvvOp: case PowvvOp: match_var = binary_match( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , hash_table_var , code // outputs ); if( match_var > 0 ) { tape[i_var].match = true; tape[match_var].match = true; tape[i_var].new_var = tape[match_var].new_var; } else { size_pair = record_vv( tape , // inputs i_var , play->num_par_rec() , play->GetPar() , rec , op , arg ); tape[i_var].new_op = size_pair.i_op; tape[i_var].new_var = size_pair.i_var; replace_hash = true; } break; // --------------------------------------------------- // Conditional expression operators case CExpOp: CPPAD_ASSERT_NARG_NRES(op, 6, 1); new_arg[0] = arg[0]; new_arg[1] = arg[1]; mask = 1; for(i = 2; i < 6; i++) { if( arg[1] & mask ) { new_arg[i] = tape[arg[i]].new_var; CPPAD_ASSERT_UNKNOWN( size_t(new_arg[i]) < num_var ); } else new_arg[i] = rec->PutPar( play->GetPar( arg[i] ) ); mask = mask << 1; } rec->PutArg( new_arg[0] , new_arg[1] , new_arg[2] , new_arg[3] , new_arg[4] , new_arg[5] ); tape[i_var].new_op = rec->num_op_rec(); tape[i_var].new_var = rec->PutOp(op); // // The new addresses for left and right are used during // fill in the arguments for the CSkip operations. This does not // affect max_left_right which is used during this sweep. CPPAD_ASSERT_UNKNOWN( cskip_info_index > 0 ); cskip_info_index--; cskip_info[ cskip_info_index ].left = new_arg[2]; cskip_info[ cskip_info_index ].right = new_arg[3]; break; // --------------------------------------------------- // Operations with no arguments and no results case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); rec->PutOp(op); break; // --------------------------------------------------- // Operations with two arguments and no results case LepvOp: case LtpvOp: case EqpvOp: case NepvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); new_arg[0] = rec->PutPar( play->GetPar(arg[0]) ); new_arg[1] = tape[arg[1]].new_var; rec->PutArg(new_arg[0], new_arg[1]); rec->PutOp(op); break; // case LevpOp: case LtvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); new_arg[0] = tape[arg[0]].new_var; new_arg[1] = rec->PutPar( play->GetPar(arg[1]) ); rec->PutArg(new_arg[0], new_arg[1]); rec->PutOp(op); break; // case LevvOp: case LtvvOp: case EqvvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); new_arg[0] = tape[arg[0]].new_var; new_arg[1] = tape[arg[1]].new_var; rec->PutArg(new_arg[0], new_arg[1]); rec->PutOp(op); break; // --------------------------------------------------- // Operations with no arguments and one result case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); tape[i_var].new_op = rec->num_op_rec(); tape[i_var].new_var = rec->PutOp(op); break; // --------------------------------------------------- // Operations with one argument that is a parameter case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); new_arg[0] = rec->PutPar( play->GetPar(arg[0] ) ); rec->PutArg( new_arg[0] ); tape[i_var].new_op = rec->num_op_rec(); tape[i_var].new_var = rec->PutOp(op); break; // --------------------------------------------------- // Load using a parameter index case LdpOp: CPPAD_ASSERT_NARG_NRES(op, 3, 1); new_arg[0] = new_vecad_ind[ arg[0] ]; new_arg[1] = arg[1]; new_arg[2] = rec->num_load_op_rec(); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind ); rec->PutArg( new_arg[0], new_arg[1], new_arg[2] ); tape[i_var].new_op = rec->num_op_rec(); tape[i_var].new_var = rec->PutLoadOp(op); break; // --------------------------------------------------- // Load using a variable index case LdvOp: CPPAD_ASSERT_NARG_NRES(op, 3, 1); new_arg[0] = new_vecad_ind[ arg[0] ]; new_arg[1] = tape[arg[1]].new_var; new_arg[2] = rec->num_load_op_rec(); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var ); rec->PutArg( new_arg[0], new_arg[1], new_arg[2] ); tape[i_var].new_var = rec->num_op_rec(); tape[i_var].new_var = rec->PutLoadOp(op); break; // --------------------------------------------------- // Store a parameter using a parameter index case StppOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); new_arg[0] = new_vecad_ind[ arg[0] ]; new_arg[1] = rec->PutPar( play->GetPar(arg[1]) ); new_arg[2] = rec->PutPar( play->GetPar(arg[2]) ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind ); rec->PutArg( new_arg[0], new_arg[1], new_arg[2] ); rec->PutOp(op); break; // --------------------------------------------------- // Store a parameter using a variable index case StvpOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); new_arg[0] = new_vecad_ind[ arg[0] ]; new_arg[1] = tape[arg[1]].new_var; new_arg[2] = rec->PutPar( play->GetPar(arg[2]) ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var ); rec->PutArg( new_arg[0], new_arg[1], new_arg[2] ); rec->PutOp(op); break; // --------------------------------------------------- // Store a variable using a parameter index case StpvOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); new_arg[0] = new_vecad_ind[ arg[0] ]; new_arg[1] = rec->PutPar( play->GetPar(arg[1]) ); new_arg[2] = tape[arg[2]].new_var; CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[2]) < num_var ); rec->PutArg( new_arg[0], new_arg[1], new_arg[2] ); rec->PutOp(op); break; // --------------------------------------------------- // Store a variable using a variable index case StvvOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); new_arg[0] = new_vecad_ind[ arg[0] ]; new_arg[1] = tape[arg[1]].new_var; new_arg[2] = tape[arg[2]].new_var; CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var ); CPPAD_ASSERT_UNKNOWN( size_t(new_arg[2]) < num_var ); rec->PutArg( new_arg[0], new_arg[1], new_arg[2] ); rec->PutOp(op); break; // ----------------------------------------------------------- case UserOp: CPPAD_ASSERT_NARG_NRES(op, 4, 0); if( user_state == user_start ) { user_state = user_arg; CPPAD_ASSERT_UNKNOWN( user_curr > 0 ); user_curr--; user_info[user_curr].op_begin = rec->num_op_rec(); } else { user_state = user_start; user_info[user_curr].op_end = rec->num_op_rec() + 1; } // user_index, user_id, user_n, user_m if( user_info[user_curr].connect_type != not_connected ) { rec->PutArg(arg[0], arg[1], arg[2], arg[3]); rec->PutOp(UserOp); } break; case UsrapOp: CPPAD_ASSERT_NARG_NRES(op, 1, 0); if( user_info[user_curr].connect_type != not_connected ) { new_arg[0] = rec->PutPar( play->GetPar(arg[0]) ); rec->PutArg(new_arg[0]); rec->PutOp(UsrapOp); } break; case UsravOp: CPPAD_ASSERT_NARG_NRES(op, 1, 0); if( user_info[user_curr].connect_type != not_connected ) { new_arg[0] = tape[arg[0]].new_var; if( size_t(new_arg[0]) < num_var ) { rec->PutArg(new_arg[0]); rec->PutOp(UsravOp); } else { // This argument does not affect the result and // has been optimized out so use nan in its place. new_arg[0] = rec->PutPar( nan(Base(0)) ); rec->PutArg(new_arg[0]); rec->PutOp(UsrapOp); } } break; case UsrrpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 0); if( user_info[user_curr].connect_type != not_connected ) { new_arg[0] = rec->PutPar( play->GetPar(arg[0]) ); rec->PutArg(new_arg[0]); rec->PutOp(UsrrpOp); } break; case UsrrvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); if( user_info[user_curr].connect_type != not_connected ) { tape[i_var].new_op = rec->num_op_rec(); tape[i_var].new_var = rec->PutOp(UsrrvOp); } break; // --------------------------------------------------- // all cases should be handled above default: CPPAD_ASSERT_UNKNOWN(false); } if( replace_hash ) { // The old variable index i_var corresponds to the // new variable index tape[i_var].new_var. In addition // this is the most recent variable that has this code. hash_table_var[code] = i_var; } } // modify the dependent variable vector to new indices for(i = 0; i < dep_taddr.size(); i++ ) { CPPAD_ASSERT_UNKNOWN( size_t(tape[dep_taddr[i]].new_var) < num_var ); dep_taddr[i] = tape[ dep_taddr[i] ].new_var; } # ifndef NDEBUG size_t num_new_op = rec->num_op_rec(); for(i_var = 0; i_var < tape.size(); i_var++) CPPAD_ASSERT_UNKNOWN( tape[i_var].new_op < num_new_op ); # endif // Move skip information from user_info to cskip_info for(i = 0; i < user_info.size(); i++) { if( user_info[i].connect_type == cexp_connected && ! user_info[i].cexp_set.empty() ) { std::set::const_iterator itr = user_info[i].cexp_set.begin(); while( itr != user_info[i].cexp_set.end() ) { j = itr->index(); k = user_info[i].op_begin; while(k < user_info[i].op_end) { if( itr->compare() == true ) cskip_info[j].skip_op_false.push_back(k++); else cskip_info[j].skip_op_true.push_back(k++); } itr++; } } } // fill in the arguments for the CSkip operations CPPAD_ASSERT_UNKNOWN( cskip_order_next == cskip_info.size() ); for(i = 0; i < cskip_info.size(); i++) { struct_cskip_info info = cskip_info[i]; if( info.i_arg > 0 ) { CPPAD_ASSERT_UNKNOWN( info.n_op_true==info.skip_op_true.size() ); CPPAD_ASSERT_UNKNOWN(info.n_op_false==info.skip_op_false.size()); size_t n_true = info.skip_var_true.size() + info.skip_op_true.size(); size_t n_false = info.skip_var_false.size() + info.skip_op_false.size(); size_t i_arg = info.i_arg; rec->ReplaceArg(i_arg++, info.cop ); rec->ReplaceArg(i_arg++, info.flag ); rec->ReplaceArg(i_arg++, info.left ); rec->ReplaceArg(i_arg++, info.right ); rec->ReplaceArg(i_arg++, n_true ); rec->ReplaceArg(i_arg++, n_false ); for(j = 0; j < info.skip_var_true.size(); j++) { i_var = info.skip_var_true[j]; if( tape[i_var].match ) { // The operation for this argument has been removed, // so use an operator index that never comes up. rec->ReplaceArg(i_arg++, rec->num_op_rec()); } else { CPPAD_ASSERT_UNKNOWN( tape[i_var].new_op > 0 ); rec->ReplaceArg(i_arg++, tape[i_var].new_op ); } } for(j = 0; j < info.skip_op_true.size(); j++) { i_op = info.skip_op_true[j]; rec->ReplaceArg(i_arg++, i_op); } for(j = 0; j < info.skip_var_false.size(); j++) { i_var = info.skip_var_false[j]; if( tape[i_var].match ) { // The operation for this argument has been removed, // so use an operator index that never comes up. rec->ReplaceArg(i_arg++, rec->num_op_rec()); } else { CPPAD_ASSERT_UNKNOWN( tape[i_var].new_op > 0 ); rec->ReplaceArg(i_arg++, tape[i_var].new_op ); } } for(j = 0; j < info.skip_op_false.size(); j++) { i_op = info.skip_op_false[j]; rec->ReplaceArg(i_arg++, i_op); } rec->ReplaceArg(i_arg++, n_true + n_false); # ifndef NDEBUG size_t n_arg = 7 + n_true + n_false; CPPAD_ASSERT_UNKNOWN( info.i_arg + n_arg == i_arg ); # endif } } } } // END_CPPAD_OPTIMIZE_NAMESPACE /*! Optimize a player object operation sequence The operation sequence for this object is replaced by one with fewer operations but the same funcition and derivative values. \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param options The default value for this option is the empty string. The only other possible value is "no_conditional_skip". If this option is present, no conditional skip operators will be generated. */ template void ADFun::optimize(const std::string& options) { // place to store the optimized version of the recording recorder rec; // number of independent variables size_t n = ind_taddr_.size(); # ifndef NDEBUG size_t i, j, m = dep_taddr_.size(); CppAD::vector x(n), y(m), check(m); Base max_taylor(0); bool check_zero_order = num_order_taylor_ > 0; if( check_zero_order ) { // zero order coefficients for independent vars for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == InvOp ); CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j+1 ); x[j] = taylor_[ ind_taddr_[j] * cap_order_taylor_ + 0]; } // zero order coefficients for dependent vars for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); y[i] = taylor_[ dep_taddr_[i] * cap_order_taylor_ + 0]; } // maximum zero order coefficient not counting BeginOp at beginning // (which is correpsonds to uninitialized memory). for(i = 1; i < num_var_tape_; i++) { if( abs_geq(taylor_[i*cap_order_taylor_+0] , max_taylor) ) max_taylor = taylor_[i*cap_order_taylor_+0]; } } # endif // create the optimized recording CppAD::optimize::optimize_run(options, n, dep_taddr_, &play_, &rec); // number of variables in the recording num_var_tape_ = rec.num_var_rec(); // now replace the recording play_.get(rec); // set flag so this function knows it has been optimized has_been_optimized_ = true; // free memory allocated for sparse Jacobian calculation // (the results are no longer valid) for_jac_sparse_pack_.resize(0, 0); for_jac_sparse_set_.resize(0,0); // free old Taylor coefficient memory taylor_.free(); num_order_taylor_ = 0; cap_order_taylor_ = 0; // resize and initilaize conditional skip vector // (must use player size because it now has the recoreder information) cskip_op_.erase(); cskip_op_.extend( play_.num_op_rec() ); # ifndef NDEBUG if( check_zero_order ) { // zero order forward calculation using new operation sequence check = Forward(0, x); // check results Base eps = 10. * epsilon(); for(i = 0; i < m; i++) CPPAD_ASSERT_KNOWN( abs_geq( eps * max_taylor , check[i] - y[i] ) , "Error during check of f.optimize()." ); // Erase memory that this calculation was done so NDEBUG gives // same final state for this object (from users perspective) num_order_taylor_ = 0; } # endif } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/discrete.hpp0000644000176200001440000002025514536067013020001 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DISCRETE_INCLUDED # define CPPAD_DISCRETE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Discrete$$ $spell retaping namespace std Eq Cpp const inline Geq $$ $section Discrete AD Functions$$ $index discrete, AD function$$ $index function, discrete AD$$ $head Syntax$$ $codei%CPPAD_DISCRETE_FUNCTION(%Base%, %name%) %$$ $icode%y% = %name%(%x%) %$$ $icode%ay% = %name%(%ax%) %$$ $head Purpose$$ Record the evaluation of a discrete function as part of an $codei%AD<%Base%>%$$ $cref/operation sequence/glossary/Operation/Sequence/$$. The value of a discrete function can depend on the $cref/independent variables/glossary/Tape/Independent Variable/$$, but its derivative is identically zero. For example, suppose that the integer part of a $cref/variable/glossary/Variable/$$ $icode x$$ is the index into an array of values. $head Base$$ This is the $cref/base type/base_require/$$ corresponding to the operations sequence; i.e., use of the $icode name$$ with arguments of type $codei%AD<%Base%>%$$ can be recorded in an operation sequence. $head name$$ This is the name of the function (as it is used in the source code). The user must provide a version of $icode name$$ where the argument has type $icode Base$$. CppAD uses this to create a version of $icode name$$ where the argument has type $codei%AD<%Base%>%$$. $head x$$ The argument $icode x$$ has prototype $codei% const %Base%& %x% %$$ It is the value at which the user provided version of $icode name$$ is to be evaluated. $head y$$ The result $icode y$$ has prototype $codei% %Base% %y% %$$ It is the return value for the user provided version of $icode name$$. $head ax$$ The argument $icode ax$$ has prototype $codei% const AD<%Base%>& %ax% %$$ It is the value at which the CppAD provided version of $icode name$$ is to be evaluated. $head ay$$ The result $icode ay$$ has prototype $codei% AD<%Base%> %ay% %$$ It is the return value for the CppAD provided version of $icode name$$. $head Create AD Version$$ $index CPPAD_DISCRETE_FUNCTION$$ The preprocessor macro invocation $codei% CPPAD_DISCRETE_FUNCTION(%Base%, %name%) %$$ defines the $codei%AD<%Base%>%$$ version of $icode name$$. This can be with in a namespace (not the $code CppAD$$ namespace) but must be outside of any routine. $head Operation Sequence$$ This is an AD of $icode Base$$ $cref/atomic operation/glossary/Operation/Atomic/$$ and hence is part of the current AD of $icode Base$$ $cref/operation sequence/glossary/Operation/Sequence/$$. $head Derivatives$$ During a zero order $cref Forward$$ operation, an $cref ADFun$$ object will compute the value of $icode name$$ using the user provided $icode Base$$ version of this routine. All the derivatives of $icode name$$ will be evaluated as zero. $head Parallel Mode$$ $index discrete, parallel$$ $index parallel, discrete$$ The first call to $codei% %ay% = %name%(%ax%) %$$ must not be in $cref/parallel/ta_in_parallel/$$ execution mode. $head Example$$ $children% example/tape_index.cpp% example/interp_onetape.cpp% example/interp_retape.cpp %$$ The file $cref tape_index.cpp$$ contains an example and test that uses a discrete function to vary an array index during $cref Forward$$ mode calculations. The file $cref interp_onetape.cpp$$ contains an example and test that uses discrete functions to avoid retaping a calculation that requires interpolation. (The file $cref interp_retape.cpp$$ shows how interpolation can be done with retaping.) $head CppADCreateDiscrete Deprecated 2007-07-28$$ $index CppADCreateDiscrete, deprecated$$ $index deprecated, CppADCreateDiscrete$$ The preprocessor symbol $code CppADCreateDiscrete$$ is defined to be the same as $code CPPAD_DISCRETE_FUNCTION$$ but its use is deprecated. $end ------------------------------------------------------------------------------ */ # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file discrete.hpp user define discrete functions */ /*! \def CPPAD_DISCRETE_FUNCTION(Base, name) Defines the function name(ax, ay) where \c ax and \c ay are vectors with AD elements. \par Base is the base type for the discrete function. \par name is the name of the user defined function that corresponding to this operation. */ # define CPPAD_DISCRETE_FUNCTION(Base, name) \ inline CppAD::AD name (const CppAD::AD& ax) \ { \ static CppAD::discrete fun(#name, name); \ \ return fun.ad(ax); \ } # define CppADCreateDiscrete CPPAD_DISCRETE_FUNCTION /* Class that acutally implemnets the ay = name(ax) call. A new discrete function is generated for ech time the user invokes the CPPAD_DISCRETE_FUNCTION macro; see static object in that macro. */ template class discrete { /// parallel_ad needs to call List to initialize static template friend void parallel_ad(void); /// type for the user routine that computes function values typedef Base (*F) (const Base& x); private: /// name of this user defined function const std::string name_; /// user's implementation of the function for Base operations const F f_; /// index of this objec in the vector of all objects for this class const size_t index_; /*! List of all objects in this class. If we use CppAD::vector for this vector, it will appear that there is a memory leak because this list is not distroyed before thread_alloc::free_available(thread) is called by the testing routines. */ static std::vector& List(void) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; static std::vector list; return list; } public: /*! Constructor called for each invocation of CPPAD_DISCRETE_FUNCTION. Put this object in the list of all objects for this class and set the constant private data name_, f_, and index_. \param Name is the user's name for this discrete function. \param f user routine that implements this function for \c Base class. \par This constructor can ont be used in parallel mode because it changes the static object \c List. */ discrete(const char* Name, F f) : name_(Name) , f_(f) , index_( List().size() ) { CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel() , "discrete: First call the function *Name is in parallel mode." ); List().push_back(this); } /*! Implement the user call to ay = name(ax). \param ax is the argument for this call. \return the return value is called \c ay above. */ AD ad(const AD &ax) const { AD ay; ay.value_ = f_(ax.value_); if( Variable(ax) ) { ADTape *tape = ax.tape_this(); CPPAD_ASSERT_UNKNOWN( NumRes(DisOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(DisOp) == 2 ); // put operand addresses in the tape tape->Rec_.PutArg(index_, ax.taddr_); // put operator in the tape ay.taddr_ = tape->Rec_.PutOp(DisOp); // make result a variable ay.tape_id_ = tape->id_; CPPAD_ASSERT_UNKNOWN( Variable(ay) ); } return ay; } /// Name corresponding to a discrete object static const char* name(size_t index) { return List()[index]->name_.c_str(); } /*! Link from forward mode sweep to users routine \param index index for this function in the list of all discrete object \param x argument value at which to evaluate this function */ static Base eval(size_t index, const Base& x) { CPPAD_ASSERT_UNKNOWN(index < List().size() ); return List()[index]->f_(x); } }; } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/opt_val_hes.hpp0000644000176200001440000003361714536067013020510 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_OPT_VAL_HES_INCLUDED # define CPPAD_OPT_VAL_HES_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin opt_val_hes$$ $spell hes sy Jacobian hes signdet jac Bradley const CppAD $$ $index Jacobian$$ $index Hessian$$ $index optimal value$$ $index value$$ $index opt_val_hes$$ $section Jacobian and Hessian of Optimal Values$$ $head Syntax$$ $icode%signdet% = opt_val_hes(%x%, %y%, %fun%, %jac%, %hes%)%$$ $head See Also$$ $cref BenderQuad$$ $head Reference$$ Algorithmic differentiation of implicit functions and optimal values, Bradley M. Bell and James V. Burke, Advances in Automatic Differentiation, 2008, Springer. $head Purpose$$ We are given a function $latex S : \B{R}^n \times \B{R}^m \rightarrow \B{R}^\ell$$ and we define $latex F : \B{R}^n \times \B{R}^m \rightarrow \B{R}$$ and $latex V : \B{R}^n \rightarrow \B{R} $$ by $latex \[ \begin{array}{rcl} F(x, y) & = & \sum_{k=0}^{\ell-1} S_k ( x , y) \\ V(x) & = & F [ x , Y(x) ] \\ 0 & = & \partial_y F [x , Y(x) ] \end{array} \] $$ We wish to compute the Jacobian and possibly also the Hessian, of $latex V (x)$$. $head BaseVector$$ The type $icode BaseVector$$ must be a $cref SimpleVector$$ class. We use $icode Base$$ to refer to the type of the elements of $icode BaseVector$$; i.e., $codei% %BaseVector%::value_type %$$ $head x$$ The argument $icode x$$ has prototype $codei% const %BaseVector%& %x% %$$ and its size must be equal to $icode n$$. It specifies the point at which we evaluating the Jacobian $latex V^{(1)} (x)$$ (and possibly the Hessian $latex V^{(2)} (x)$$). $head y$$ The argument $icode y$$ has prototype $codei% const %BaseVector%& %y% %$$ and its size must be equal to $icode m$$. It must be equal to $latex Y(x)$$; i.e., it must solve the implicit equation $latex \[ 0 = \partial_y F ( x , y) \] $$ $head Fun$$ The argument $icode fun$$ is an object of type $icode Fun$$ which must support the member functions listed below. CppAD will may be recording operations of the type $codei%AD<%Base%>%$$ when these member functions are called. These member functions must not stop such a recording; e.g., they must not call $cref/AD::abort_recording/abort_recording/$$. $subhead Fun::ad_vector$$ The type $icode%Fun%::ad_vector%$$ must be a $cref SimpleVector$$ class with elements of type $codei%AD<%Base%>%$$; i.e. $codei% %Fun%::ad_vector::value_type %$$ is equal to $codei%AD<%Base%>%$$. $subhead fun.ell$$ The type $icode Fun$$ must support the syntax $codei% %ell% = %fun%.ell() %$$ where $icode ell$$ has prototype $codei% size_t %ell% %$$ and is the value of $latex \ell$$; i.e., the number of terms in the summation. $pre $$ One can choose $icode ell$$ equal to one, and have $latex S(x,y)$$ the same as $latex F(x, y)$$. Each of the functions $latex S_k (x , y)$$, (in the summation defining $latex F(x, y)$$) is differentiated separately using AD. For very large problems, breaking $latex F(x, y)$$ into the sum of separate simpler functions may reduce the amount of memory necessary for algorithmic differentiation and there by speed up the process. $subhead fun.s$$ The type $icode Fun$$ must support the syntax $codei% %s_k% = %fun%.s(%k%, %x%, %y%) %$$ The $icode%fun%.s%$$ argument $icode k$$ has prototype $codei% size_t %k% %$$ and is between zero and $icode%ell% - 1%$$. The argument $icode x$$ to $icode%fun%.s%$$ has prototype $codei% const %Fun%::ad_vector& %x% %$$ and its size must be equal to $icode n$$. The argument $icode y$$ to $icode%fun%.s%$$ has prototype $codei% const %Fun%::ad_vector& %y% %$$ and its size must be equal to $icode m$$. The $icode%fun%.s%$$ result $icode s_k$$ has prototype $codei% AD<%Base%> %s_k% %$$ and its value must be given by $latex s_k = S_k ( x , y )$$. $subhead fun.sy$$ The type $icode Fun$$ must support the syntax $codei% %sy_k% = %fun%.sy(%k%, %x%, %y%) %$$ The argument $icode k$$ to $icode%fun%.sy%$$ has prototype $codei% size_t %k% %$$ The argument $icode x$$ to $icode%fun%.sy%$$ has prototype $codei% const %Fun%::ad_vector& %x% %$$ and its size must be equal to $icode n$$. The argument $icode y$$ to $icode%fun%.sy%$$ has prototype $codei% const %Fun%::ad_vector& %y% %$$ and its size must be equal to $icode m$$. The $icode%fun%.sy%$$ result $icode sy_k$$ has prototype $codei% %Fun%::ad_vector %sy_k% %$$ its size must be equal to $icode m$$, and its value must be given by $latex sy_k = \partial_y S_k ( x , y )$$. $head jac$$ The argument $icode jac$$ has prototype $codei% %BaseVector%& %jac% %$$ and has size $icode n$$ or zero. The input values of its elements do not matter. If it has size zero, it is not affected. Otherwise, on output it contains the Jacobian of $latex V (x)$$; i.e., for $latex j = 0 , \ldots , n-1$$, $latex \[ jac[ j ] = V^{(1)} (x)_j \] $$ where $icode x$$ is the first argument to $code opt_val_hes$$. $head hes$$ The argument $icode hes$$ has prototype $codei% %BaseVector%& %hes% %$$ and has size $icode%n% * %n%$$ or zero. The input values of its elements do not matter. If it has size zero, it is not affected. Otherwise, on output it contains the Hessian of $latex V (x)$$; i.e., for $latex i = 0 , \ldots , n-1$$, and $latex j = 0 , \ldots , n-1$$, $latex \[ hes[ i * n + j ] = V^{(2)} (x)_{i,j} \] $$ $head signdet$$ If $icode%hes%$$ has size zero, $icode signdet$$ is not defined. Otherwise the return value $icode signdet$$ is the sign of the determinant for $latex \partial_{yy}^2 F(x , y) $$. If it is zero, then the matrix is singular and the Hessian is not computed ($icode hes$$ is not changed). $head Example$$ $children% example/opt_val_hes.cpp %$$ The file $cref opt_val_hes.cpp$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ----------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file opt_val_hes.hpp \brief Computing Jabobians and Hessians of Optimal Values */ /*! Computing Jabobians and Hessians of Optimal Values We are given a function \f$ S : {\rm R}^n \times {\rm R}^m \rightarrow {\rm R}^\ell \f$ and we define \f$ F : {\rm R}^n \times {\rm R}^m \rightarrow {\rm R} \f$ and \f$ V : {\rm R}^n \rightarrow {\rm R} \f$ by \f[ \begin{array}{rcl} F(x, y) & = & \sum_{k=0}^{\ell-1} S_k ( x , y) \\ V(x) & = & F [ x , Y(x) ] \\ 0 & = & \partial_y F [x , Y(x) ] \end{array} \f] We wish to compute the Jacobian and possibly also the Hessian, of \f$ V (x) \f$. \tparam BaseVector The type \c BaseVector must be a SimpleVector class. We use \c Base to refer to the type of the elements of \c BaseVector; i.e., BaseVector::value_type. \param x is a vector with size \c n. It specifies the point at which we evaluating the Jacobian \f$ V^{(1)} (x) \f$ (and possibly the Hessian \f$ V^{(2)} (x) \f$). \param y is a vector with size \c m. It must be equal to \f$ Y(x) \f$; i.e., it must solve the implicit equation \f[ 0 = \partial_y F ( x , y) \f] \param fun The argument \c fun is an object of type \c Fun wich must support the member functions listed below. CppAD will may be recording operations of the type \c AD when these member functions are called. These member functions must not stop such a recording; e.g., they must not call \c AD::abort_recording. \par Fun::ad_vector The type Fun::ad_vector must be a SimpleVector class with elements of type \c AD; i.e. Fun::ad_vector::value_type is equal to \c AD. \par fun.ell the type \c Fun must support the syntax \verbatim ell = fun.ell() \endverbatim where \c ell is a \c size_t value that is set to \f$ \ell \f$; i.e., the number of terms in the summation. \par fun.s The type \c Fun must support the syntax \verbatim s_k = fun.s(k, x, y) \endverbatim The argument \c k has prototype size_t k. The argument \c x has prototype const Fun::ad_vector& x and its size must be equal to \c n. The argument \c y has prototype const Fun::ad_vector& y and its size must be equal to \c m. The return value \c s_k has prototype \c AD s_k and its value must be given by \f$ s_k = S_k ( x , y ) \f$. \par fun.sy The type \c Fun must support the syntax \verbatim sy_k = fun.sy(k, x, y) \endverbatim The argument \c k has prototype size_t k. The argument \c x has prototype const Fun::ad_vector& x and its size must be equal to \c n. The argument \c y has prototype const Fun::ad_vector& y and its size must be equal to \c m. The return value \c sy_k has prototype Fun::ad_vector& sy_k, its size is \c m and its value must be given by \f$ sy_k = \partial_y S_k ( x , y ) \f$. \param jac is a vector with size \c n or zero. The input values of its elements do not matter. If it has size zero, it is not affected. Otherwise, on output it contains the Jacobian of \f$ V (x) \f$; i.e., for \f$ j = 0 , \ldots , n-1 \f$, \f[ jac[ j ] = V^{(1)} (x)_j \f] $$ where \c x is the first argument to \c opt_val_hes. \param hes is a vector with size n * n or zero. The input values of its elements do not matter. If it has size zero, it is not affected. Otherwise, on output it contains the Hessian of \f$ V (x) \f$; i.e., for \f$ i = 0 , \ldots , n-1 \f$, and \f$ j = 0 , \ldots , n-1 \f$, \f[ hes[ i * n + j ] = V^{(2)} (x)_{i,j} \f] \return If hes.size() == 0, the return value is not defined. Otherwise, the return value is the sign of the determinant for \f$ \partial_{yy}^2 F(x , y) \f$$. If it is zero, then the matrix is singular and \c hes is not set to its specified value. */ template int opt_val_hes( const BaseVector& x , const BaseVector& y , Fun fun , BaseVector& jac , BaseVector& hes ) { // determine the base type typedef typename BaseVector::value_type Base; // check that BaseVector is a SimpleVector class with Base elements CheckSimpleVector(); // determine the AD vector type typedef typename Fun::ad_vector ad_vector; // check that ad_vector is a SimpleVector class with AD elements CheckSimpleVector< AD , ad_vector >(); // size of the x and y spaces size_t n = size_t(x.size()); size_t m = size_t(y.size()); // number of terms in the summation size_t ell = fun.ell(); // check size of return values CPPAD_ASSERT_KNOWN( size_t(jac.size()) == n || jac.size() == 0, "opt_val_hes: size of the vector jac is not equal to n or zero" ); CPPAD_ASSERT_KNOWN( size_t(hes.size()) == n * n || hes.size() == 0, "opt_val_hes: size of the vector hes is not equal to n * n or zero" ); // some temporary indices size_t i, j, k; // AD version of S_k(x, y) ad_vector s_k(1); // ADFun version of S_k(x, y) ADFun S_k; // AD version of x ad_vector a_x(n); // AD version of y ad_vector a_y(n); if( jac.size() > 0 ) { // this is the easy part, computing the V^{(1)} (x) which is equal // to \partial_x F (x, y) (see Thoerem 2 of the reference). // copy x and y to AD version for(j = 0; j < n; j++) a_x[j] = x[j]; for(j = 0; j < m; j++) a_y[j] = y[j]; // initialize summation for(j = 0; j < n; j++) jac[j] = Base(0.); // add in \partial_x S_k (x, y) for(k = 0; k < ell; k++) { // start recording Independent(a_x); // record s_k[0] = fun.s(k, a_x, a_y); // stop recording and store in S_k S_k.Dependent(a_x, s_k); // compute partial of S_k with respect to x BaseVector jac_k = S_k.Jacobian(x); // add \partial_x S_k (x, y) to jac for(j = 0; j < n; j++) jac[j] += jac_k[j]; } } // check if we are done if( hes.size() == 0 ) return 0; /* In this case, we need to compute the Hessian. Using Theorem 1 of the reference: Y^{(1)}(x) = - F_yy (x, y)^{-1} F_yx (x, y) Using Theorem 2 of the reference: V^{(2)}(x) = F_xx (x, y) + F_xy (x, y) Y^{(1)}(x) */ // Base and AD version of xy BaseVector xy(n + m); ad_vector a_xy(n + m); for(j = 0; j < n; j++) a_xy[j] = xy[j] = x[j]; for(j = 0; j < m; j++) a_xy[n+j] = xy[n+j] = y[j]; // Initialization summation for Hessian of F size_t nm_sq = (n + m) * (n + m); BaseVector F_hes(nm_sq); for(j = 0; j < nm_sq; j++) F_hes[j] = Base(0.); BaseVector hes_k(nm_sq); // add in Hessian of S_k to hes for(k = 0; k < ell; k++) { // start recording Independent(a_xy); // split out x for(j = 0; j < n; j++) a_x[j] = a_xy[j]; // split out y for(j = 0; j < m; j++) a_y[j] = a_xy[n+j]; // record s_k[0] = fun.s(k, a_x, a_y); // stop recording and store in S_k S_k.Dependent(a_xy, s_k); // when computing the Hessian it pays to optimize the tape S_k.optimize(); // compute Hessian of S_k hes_k = S_k.Hessian(xy, 0); // add \partial_x S_k (x, y) to jac for(j = 0; j < nm_sq; j++) F_hes[j] += hes_k[j]; } // Extract F_yx BaseVector F_yx(m * n); for(i = 0; i < m; i++) { for(j = 0; j < n; j++) F_yx[i * n + j] = F_hes[ (i+n)*(n+m) + j ]; } // Extract F_yy BaseVector F_yy(n * m); for(i = 0; i < m; i++) { for(j = 0; j < m; j++) F_yy[i * m + j] = F_hes[ (i+n)*(n+m) + j + n ]; } // compute - Y^{(1)}(x) = F_yy (x, y)^{-1} F_yx (x, y) BaseVector neg_Y_x(m * n); Base logdet; int signdet = CppAD::LuSolve(m, n, F_yy, F_yx, neg_Y_x, logdet); if( signdet == 0 ) return signdet; // compute hes = F_xx (x, y) + F_xy (x, y) Y^{(1)}(x) for(i = 0; i < n; i++) { for(j = 0; j < n; j++) { hes[i * n + j] = F_hes[ i*(n+m) + j ]; for(k = 0; k < m; k++) hes[i*n+j] -= F_hes[i*(n+m) + k+n] * neg_Y_x[k*n+j]; } } return signdet; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/local/csum_op.hpp0000644000176200001440000004263014536067013017645 0ustar liggesusers// $Id$ # ifndef CPPAD_CSUM_OP_INCLUDED # define CPPAD_CSUM_OP_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file csum_op.hpp Forward, reverse and sparsity calculations for cummulative summation. */ /*! Compute forward mode Taylor coefficients for result of op = CsumOp. This operation is \verbatim z = s + x(1) + ... + x(m) - y(1) - ... - y(n). \endverbatim \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param p lowest order of the Taylor coefficient that we are computing. \param q highest order of the Taylor coefficient that we are computing. \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param arg \a arg[0] is the number of addition variables in this cummulative summation; i.e., m. \n \a arg[1] is the number of subtraction variables in this cummulative summation; i.e., \c m. \n parameter[ arg[2] ] is the parameter value \c s in this cummunative summation. \n arg[2+i] for i = 1 , ... , m is the variable index of x(i). \n arg[2+arg[0]+i] for i = 1 , ... , n is the variable index of y(i). \param num_par is the number of parameters in \a parameter. \param parameter is the parameter vector for this operation sequence. \param cap_order number of colums in the matrix containing all the Taylor coefficients. \param taylor \b Input: taylor [ arg[2+i] * cap_order + k ] for i = 1 , ... , m and k = 0 , ... , q is the k-th order Taylor coefficient corresponding to x(i) \n \b Input: taylor [ arg[2+m+i] * cap_order + k ] for i = 1 , ... , n and k = 0 , ... , q is the k-th order Taylor coefficient corresponding to y(i) \n \b Input: taylor [ i_z * cap_order + k ] for k = 0 , ... , p, is the k-th order Taylor coefficient corresponding to z. \n \b Output: taylor [ i_z * cap_order + k ] for k = p , ... , q, is the \a k-th order Taylor coefficient corresponding to z. */ template inline void forward_csum_op( size_t p , size_t q , size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , Base* taylor ) { Base zero(0); size_t i, j, k; // check assumptions CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); CPPAD_ASSERT_UNKNOWN( arg[0] + arg[1] == arg[ arg[0] + arg[1] + 3 ] ); // Taylor coefficients corresponding to result Base* z = taylor + i_z * cap_order; for(k = p; k <= q; k++) z[k] = zero; if( p == 0 ) z[p] = parameter[ arg[2] ]; Base* x; i = arg[0]; j = 2; while(i--) { CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z ); x = taylor + arg[++j] * cap_order; for(k = p; k <= q; k++) z[k] += x[k]; } i = arg[1]; while(i--) { CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z ); x = taylor + arg[++j] * cap_order; for(k = p; k <= q; k++) z[k] -= x[k]; } } /*! Multiple direction forward mode Taylor coefficients for op = CsumOp. This operation is \verbatim z = s + x(1) + ... + x(m) - y(1) - ... - y(n). \endverbatim \tparam Base base type for the operator; i.e., this operation was recorded using AD and computations by this routine are done using type \a Base. \param q order ot the Taylor coefficients that we are computing. \param r number of directions for Taylor coefficients that we are computing. \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param arg \a arg[0] is the number of addition variables in this cummulative summation; i.e., m. \n \a arg[1] is the number of subtraction variables in this cummulative summation; i.e., \c m. \n parameter[ arg[2] ] is the parameter value \c s in this cummunative summation. \n arg[2+i] for i = 1 , ... , m is the variable index of x(i). \n arg[2+arg[0]+i] for i = 1 , ... , n is the variable index of y(i). \param num_par is the number of parameters in \a parameter. \param parameter is the parameter vector for this operation sequence. \param cap_order number of colums in the matrix containing all the Taylor coefficients. \param taylor \b Input: taylor [ arg[2+i]*((cap_order-1)*r + 1) + 0 ] for i = 1 , ... , m is the 0-th order Taylor coefficient corresponding to x(i) and taylor [ arg[2+i]*((cap_order-1)*r + 1) + (q-1)*r + ell + 1 ] for i = 1 , ... , m, ell = 0 , ... , r-1 is the q-th order Taylor coefficient corresponding to x(i) and direction ell. \n \b Input: taylor [ arg[2+m+i]*((cap_order-1)*r + 1) + 0 ] for i = 1 , ... , n is the 0-th order Taylor coefficient corresponding to y(i) and taylor [ arg[2+m+i]*((cap_order-1)*r + 1) + (q-1)*r + ell + 1 ] for i = 1 , ... , n, ell = 0 , ... , r-1 is the q-th order Taylor coefficient corresponding to y(i) and direction ell. \n \b Output: taylor [ i_z*((cap_order-1)*r+1) + (q-1)*r + ell + 1 ] is the \a q-th order Taylor coefficient corresponding to z for direction ell = 0 , ... , r-1. */ template inline void forward_csum_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , Base* taylor ) { Base zero(0); size_t i, j, ell; // check assumptions CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); CPPAD_ASSERT_UNKNOWN( arg[0] + arg[1] == arg[ arg[0] + arg[1] + 3 ] ); // Taylor coefficients corresponding to result size_t num_taylor_per_var = (cap_order-1) * r + 1; size_t m = (q-1)*r + 1; Base* z = taylor + i_z * num_taylor_per_var + m; for(ell = 0; ell < r; ell++) z[ell] = zero; Base* x; i = arg[0]; j = 2; while(i--) { CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z ); x = taylor + arg[++j] * num_taylor_per_var + m; for(ell = 0; ell < r; ell++) z[ell] += x[ell]; } i = arg[1]; while(i--) { CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z ); x = taylor + arg[++j] * num_taylor_per_var + m; for(ell = 0; ell < r; ell++) z[ell] -= x[ell]; } } /*! Compute reverse mode Taylor coefficients for result of op = CsumOp. This operation is \verbatim z = q + x(1) + ... + x(m) - y(1) - ... - y(n). H(y, x, w, ...) = G[ z(x, y), y, x, w, ... ] \endverbatim \tparam Base base type for the operator; i.e., this operation was recorded using AD< \a Base > and computations by this routine are done using type \a Base. \param d order the highest order Taylor coefficient that we are computing the partial derivatives with respect to. \param i_z variable index corresponding to the result for this operation; i.e. the row index in \a taylor corresponding to z. \param arg \a arg[0] is the number of addition variables in this cummulative summation; i.e., m. \n \a arg[1] is the number of subtraction variables in this cummulative summation; i.e., \c m. \n parameter[ arg[2] ] is the parameter value \c q in this cummunative summation. \n arg[2+i] for i = 1 , ... , m is the value x(i). \n arg[2+arg[0]+i] for i = 1 , ... , n is the value y(i). \param nc_partial number of colums in the matrix containing all the partial derivatives. \param partial \b Input: partial [ arg[2+i] * nc_partial + k ] for i = 1 , ... , m and k = 0 , ... , d is the partial derivative of G(z, y, x, w, ...) with respect to the k-th order Taylor coefficient corresponding to x(i) \n \b Input: partial [ arg[2+m+i] * nc_partial + k ] for i = 1 , ... , n and k = 0 , ... , d is the partial derivative of G(z, y, x, w, ...) with respect to the k-th order Taylor coefficient corresponding to y(i) \n \b Input: partial [ i_z * nc_partial + k ] for i = 1 , ... , n and k = 0 , ... , d is the partial derivative of G(z, y, x, w, ...) with respect to the k-th order Taylor coefficient corresponding to \c z. \n \b Output: partial [ arg[2+i] * nc_partial + k ] for i = 1 , ... , m and k = 0 , ... , d is the partial derivative of H(y, x, w, ...) with respect to the k-th order Taylor coefficient corresponding to x(i) \n \b Output: partial [ arg[2+m+i] * nc_partial + k ] for i = 1 , ... , n and k = 0 , ... , d is the partial derivative of H(y, x, w, ...) with respect to the k-th order Taylor coefficient corresponding to y(i) */ template inline void reverse_csum_op( size_t d , size_t i_z , const addr_t* arg , size_t nc_partial , Base* partial ) { // check assumptions CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // Taylor coefficients and partial derivative corresponding to result Base* pz = partial + i_z * nc_partial; Base* px; size_t i, j, k; size_t d1 = d + 1; i = arg[0]; j = 2; while(i--) { CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z ); px = partial + arg[++j] * nc_partial; k = d1; while(k--) px[k] += pz[k]; } i = arg[1]; while(i--) { CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z ); px = partial + arg[++j] * nc_partial; k = d1; while(k--) px[k] -= pz[k]; } } /*! Forward mode Jacobian sparsity pattern for CSumOp operator. This operation is \verbatim z = q + x(1) + ... + x(m) - y(1) - ... - y(n). \endverbatim \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e. the index in \a sparsity corresponding to z. \param arg \a arg[0] is the number of addition variables in this cummulative summation; i.e., m + n. \n \a arg[1] is the number of subtraction variables in this cummulative summation; i.e., \c m. \n parameter[ arg[2] ] is the parameter value \c q in this cummunative summation. \n arg[2+i] for i = 1 , ... , m is the value x(i). \n arg[2+arg[1]+i] for i = 1 , ... , n is the value y(i). \param sparsity \b Input: For i = 1 , ... , m, the set with index \a arg[2+i] in \a sparsity is the sparsity bit pattern for x(i). This identifies which of the independent variables the variable x(i) depends on. \n \b Input: For i = 1 , ... , n, the set with index \a arg[2+arg[0]+i] in \a sparsity is the sparsity bit pattern for x(i). This identifies which of the independent variables the variable y(i) depends on. \n \b Output: The set with index \a i_z in \a sparsity is the sparsity bit pattern for z. This identifies which of the independent variables the variable z depends on. */ template inline void forward_sparse_jacobian_csum_op( size_t i_z , const addr_t* arg , Vector_set& sparsity ) { sparsity.clear(i_z); size_t i, j; i = arg[0] + arg[1]; j = 2; while(i--) { CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z ); sparsity.binary_union( i_z , // index in sparsity for result i_z , // index in sparsity for left operand arg[++j] , // index for right operand sparsity // sparsity vector for right operand ); } } /*! Reverse mode Jacobian sparsity pattern for CSumOp operator. This operation is \verbatim z = q + x(1) + ... + x(m) - y(1) - ... - y(n). H(y, x, w, ...) = G[ z(x, y), y, x, w, ... ] \endverbatim \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e. the index in \a sparsity corresponding to z. \param arg \a arg[0] is the number of addition variables in this cummulative summation; i.e., m + n. \n \a arg[1] is the number of subtraction variables in this cummulative summation; i.e., \c m. \n parameter[ arg[2] ] is the parameter value \c q in this cummunative summation. \n arg[2+i] for i = 1 , ... , m is the value x(i). \n arg[2+arg[1]+i] for i = 1 , ... , n is the value y(i). \param sparsity For i = 1 , ... , m, the set with index \a arg[2+i] in \a sparsity is the sparsity bit pattern for x(i). This identifies which of the dependent variables depend on x(i). On input, the sparsity patter corresponds to \c G, and on ouput it corresponds to \c H. \n For i = 1 , ... , m, the set with index \a arg[2+arg[0]+i] in \a sparsity is the sparsity bit pattern for y(i). This identifies which of the dependent variables depend on y(i). On input, the sparsity patter corresponds to \c G, and on ouput it corresponds to \c H. \n \b Input: The set with index \a i_z in \a sparsity is the sparsity bit pattern for z. On input it corresponds to \c G and on output it is undefined. */ template inline void reverse_sparse_jacobian_csum_op( size_t i_z , const addr_t* arg , Vector_set& sparsity ) { size_t i, j; i = arg[0] + arg[1]; j = 2; while(i--) { ++j; CPPAD_ASSERT_UNKNOWN( size_t(arg[j]) < i_z ); sparsity.binary_union( arg[j] , // index in sparsity for result arg[j] , // index in sparsity for left operand i_z , // index for right operand sparsity // sparsity vector for right operand ); } } /*! Reverse mode Hessian sparsity pattern for CSumOp operator. This operation is \verbatim z = q + x(1) + ... + x(m) - y(1) - ... - y(n). H(y, x, w, ...) = G[ z(x, y), y, x, w, ... ] \endverbatim \tparam Vector_set is the type used for vectors of sets. It can be either \c sparse_pack, \c sparse_set, or \c sparse_list. \param i_z variable index corresponding to the result for this operation; i.e. the index in \a sparsity corresponding to z. \param arg \a arg[0] is the number of addition variables in this cummulative summation; i.e., m + n. \n \a arg[1] is the number of subtraction variables in this cummulative summation; i.e., \c m. \n parameter[ arg[2] ] is the parameter value \c q in this cummunative summation. \n arg[2+i] for i = 1 , ... , m is the value x(i). \n arg[2+arg[0]+i] for i = 1 , ... , n is the value y(i). \param rev_jacobian rev_jacobian[i_z] is all false (true) if the Jabobian of G with respect to z must be zero (may be non-zero). \n \n For i = 1 , ... , m rev_jacobian[ arg[2+i] ] is all false (true) if the Jacobian with respect to x(i) is zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. \n \n For i = 1 , ... , n rev_jacobian[ arg[2+arg[0]+i] ] is all false (true) if the Jacobian with respect to y(i) is zero (may be non-zero). On input, it corresponds to the function G, and on output it corresponds to the function H. \param rev_hes_sparsity The set with index \a i_z in in \a rev_hes_sparsity is the Hessian sparsity pattern for the fucntion G where one of the partials derivative is with respect to z. \n \n For i = 1 , ... , m The set with index arg[2+i] in \a rev_hes_sparsity is the Hessian sparsity pattern where one of the partials derivative is with respect to x(i). On input, it corresponds to the function G, and on output it corresponds to the function H. \n \n For i = 1 , ... , n The set with index arg[2+arg[0]+i] in \a rev_hes_sparsity is the Hessian sparsity pattern where one of the partials derivative is with respect to y(i). On input, it corresponds to the function G, and on output it corresponds to the function H. */ template inline void reverse_sparse_hessian_csum_op( size_t i_z , const addr_t* arg , bool* rev_jacobian , Vector_set& rev_hes_sparsity ) { size_t i, j; i = arg[0] + arg[1]; j = 2; while(i--) { ++j; CPPAD_ASSERT_UNKNOWN( size_t(arg[j]) < i_z ); rev_hes_sparsity.binary_union( arg[j] , // index in sparsity for result arg[j] , // index in sparsity for left operand i_z , // index for right operand rev_hes_sparsity // sparsity vector for right operand ); rev_jacobian[arg[j]] |= rev_jacobian[i_z]; } } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/index_sort.hpp0000644000176200001440000001046114536067012017260 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_INDEX_SORT_INCLUDED # define CPPAD_INDEX_SORT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin index_sort$$ $spell cppad.hpp ind const $$ $section Returns Indices that Sort a Vector$$ $index index_sort$$ $index sort, index$$ $head Syntax$$ $codei%# include index_sort(%keys%, %ind%)%$$ $head keys$$ The argument $icode keys$$ has prototype $codei% const %VectorKey%& %keys% %$$ where $icode VectorKey$$ is a $cref SimpleVector$$ class with elements that support the $code <$$ operation. $head ind$$ The argument $icode ind$$ has prototype $codei% const %VectorSize%& %ind% %$$ where $icode VectorSize$$ is a $cref SimpleVector$$ class with elements of type $code size_t$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. The size of $icode ind$$ must be the same as the size of $icode keys$$ and the value of its input elements does not matter. $pre $$ Upon return, $icode ind$$ is a permutation of the set of indices that yields increasing order for $icode keys$$. In other words, for all $icode%i% != %j%$$, $codei% %ind%[%i%] != %ind%[%j%] %$$ and for $icode%i% = 0 , %...% , %size%-2%$$, $codei% ( %keys%[ %ind%[%i%+1] ] < %keys%[ %ind%[%i%] ] ) == false %$$ $head Example$$ $children% example/index_sort.cpp %$$ The file $cref index_sort.cpp$$ contains an example and test of this routine. It return true if it succeeds and false otherwise. $end */ # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file index_sort.hpp File used to implement the CppAD index sort utility */ /*! Helper class used by index_sort */ template class index_sort_element { private: /// key used to determine position of this element Compare key_; /// index vlaue corresponding to this key size_t index_; public: /// operator requried by std::sort bool operator<(const index_sort_element& other) const { return key_ < other.key_; } /// set the key for this element void set_key(const Compare& value) { key_ = value; } /// set the index for this element void set_index(const size_t& index) { index_ = index; } /// get the key for this element Compare get_key(void) const { return key_; } /// get the index for this element size_t get_index(void) const { return index_; } }; /*! Compute the indices that sort a vector of keys \tparam VectorKey Simple vector type that deterimene the sorting order by \c < operator on its elements. \tparam VectorSize Simple vector type with elements of \c size_t that is used to return index values. \param keys [in] values that determine the sorting order. \param ind [out] must have the same size as \c keys. The input value of its elements does not matter. The output value of its elements satisfy \code ( keys[ ind[i] ] < keys[ ind[i+1] ] ) == false \endcode */ template void index_sort(const VectorKey& keys, VectorSize& ind) { typedef typename VectorKey::value_type Compare; CheckSimpleVector(); typedef index_sort_element element; CPPAD_ASSERT_KNOWN( size_t(keys.size()) == size_t(ind.size()), "index_sort: vector sizes do not match" ); size_t size_work = size_t(keys.size()); size_t size_out; element* work = thread_alloc::create_array(size_work, size_out); // copy initial order into work size_t i; for(i = 0; i < size_work; i++) { work[i].set_key( keys[i] ); work[i].set_index( i ); } // sort the work array std::sort(work, work+size_work); // copy the indices to the output vector for(i = 0; i < size_work; i++) ind[i] = work[i].get_index(); // we are done with this work array thread_alloc::delete_array(work); return; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/vector.hpp0000644000176200001440000005624114536067013016413 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_VECTOR_INCLUDED # define CPPAD_VECTOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin CppAD_vector$$ $spell rvalues thread_alloc cppad.hpp Bool resize Rcout endl std Cpp const vec ostream elem $$ $index vector, CppAD template class$$ $index class, template CppAD vector$$ $index template, CppAD vector class$$ $section The CppAD::vector Template Class$$ $head Syntax$$ $code # include $$ $head Description$$ The include file $code cppad/vector.hpp$$ defines the vector template class $code CppAD::vector$$. This is a $cref SimpleVector$$ template class and in addition it has the features listed below: $head Include$$ The file $code cppad/vector.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the CppAD include files. $head capacity$$ If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$, and $icode cap$$ is a $code size_t$$ object, $codei% %cap% = %x%.capacity() %$$ set $icode cap$$ to the number of $icode Scalar$$ objects that could fit in the memory currently allocated for $icode x$$. Note that $codei% %x%.size() <= %x%.capacity() %$$ $head Assignment$$ $index assignment, CppAD vector$$ If $icode x$$ and $icode y$$ are $codei%CppAD::vector<%Scalar%>%$$ objects, $codei% %y% = %x% %$$ has all the properties listed for a $cref/simple vector assignment/SimpleVector/Assignment/$$ plus the following: $subhead Check Size$$ The $code CppAD::vector$$ template class will check that the size of $icode x$$ is either zero or the size of $icode y$$ before doing the assignment. If this is not the case, $code CppAD::vector$$ will use $cref ErrorHandler$$ to generate an appropriate error report. Allowing for assignment to a vector with size zero makes the following code work: $codei% CppAD::vector<%Scalar%> %y%; %y% = %x%; %$$ $subhead Return Reference$$ A reference to the vector $icode y$$ is returned. An example use of this reference is in multiple assignments of the form $codei% %z% = %y% = %x% %$$ $subhead Move Semantics$$ If the C++ compiler supports move semantic rvalues using the $code &&$$ syntax, then it will be used during the vector assignment statement. This means that return values and other temporaries are not be copied, but rather pointers are transferred. $head Element Access$$ $index [], CppAD vector$$ $index vector, [] CppAD$$ If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object and $code i$$ has type $code size_t$$, $codei% %x%[%i%] %$$ has all the properties listed for a $cref/simple vector element access/SimpleVector/Element Access/$$ plus the following: $pre $$ The object $icode%x%[%i%]%$$ has type $icode Scalar$$ (is not possibly a different type that can be converted to $icode Scalar$$). $pre $$ If $icode i$$ is not less than the size of the $icode x$$, $code CppAD::vector$$ will use $cref ErrorHandler$$ to generate an appropriate error report. $head push_back$$ $index push_back, CppAD vector$$ $index vector, CppAD push_back$$ If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object with size equal to $icode n$$ and $icode s$$ has type $icode Scalar$$, $codei% %x%.push_back(%s%) %$$ extends the vector $icode x$$ so that its new size is $icode n$$ plus one and $icode%x%[%n%]%$$ is equal to $icode s$$ (equal in the sense of the $icode Scalar$$ assignment operator). $head push_vector$$ $index push_vector, CppAD$$ $index vector, CppAD push$$ If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object with size equal to $icode n$$ and $icode v$$ is a $cref/simple vector/SimpleVector/$$ with elements of type $icode Scalar$$ and size $icode m$$, $codei% %x%.push_vector(%v%) %$$ extends the vector $icode x$$ so that its new size is $icode%n%+%m%$$ and $icode%x%[%n% + %i%]%$$ is equal to $icode%v%[%i%]%$$ for $icode%i = 1 , ... , m-1%$$ (equal in the sense of the $icode Scalar$$ assignment operator). $head Output$$ If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object and $icode os$$ is an $code std::ostream$$, and the operation $codei% %os% << %x% %$$ will output the vector $icode x$$ to the standard output stream $icode os$$. The elements of $icode x$$ are enclosed at the beginning by a $code {$$ character, they are separated by $code ,$$ characters, and they are enclosed at the end by $code }$$ character. It is assumed by this operation that if $icode e$$ is an object with type $icode Scalar$$, $codei% %os% << %e% %$$ will output the value $icode e$$ to the standard output stream $icode os$$. $head resize$$ The call $icode%x%.resize(%n%)%$$ set the size of $icode x$$ equal to $icode n$$. If $icode%n% <= %x%.capacity()%$$, no memory is freed or allocated and the capacity of $icode x$$ does not change. $head clear$$ All memory allocated for the vector is freed and both its size and capacity are set to zero. The can be useful when using very large vectors and when checking for memory leaks (and there are global vectors) see the $cref/memory/CppAD_vector/Memory and Parallel Mode/$$ discussion. $head data$$ $index data, CppAD vector$$ $index vector, CppAD data$$ If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object $codei% %x%.data() %$$ returns a pointer to a $icode Scalar$$ object such that for $codei%0 <= %i% < %x%.size()%$$, $icode%x%[%i%]%$$ and $icode%x%.data()[%i%]%$$ are the same $icode Scalar$$ object. If $icode x$$ is $code const$$, the pointer is $code const$$. If $icode%x%.capacity()%$$ is zero, the value of the pointer is not defined. The pointer may no longer be valid after the following operations on $icode x$$: its destructor, $code clear$$, $code resize$$, $code push_back$$, $code push_vector$$, assignment to another vector when original size of $icode x$$ is zero. $head vectorBool$$ $index vectorBool$$ The file $code $$ also defines the class $code CppAD::vectorBool$$. This has the same specifications as $code CppAD::vector$$ with the following exceptions: $subhead Memory$$ The class $code vectorBool$$ conserves on memory (on the other hand, $code CppAD::vector$$ is expected to be faster than $code vectorBool$$). $subhead data$$ The $cref/data/CppAD_vector/data/$$ function is not supported by $code vectorBool$$. $subhead Output$$ The $code CppAD::vectorBool$$ output operator prints each boolean value as a $code 0$$ for false, a $code 1$$ for true, and does not print any other output; i.e., the vector is written a long sequence of zeros and ones with no surrounding $code {$$, $code }$$ and with no separating commas or spaces. $subhead Element Type$$ If $icode x$$ has type $code vectorBool$$ and $icode i$$ has type $code size_t$$, the element access value $icode%x%[%i%]%$$ has an unspecified type, referred to here as $icode elementType$$, that supports the following operations: $list number$$ $icode elementType$$ can be converted to $code bool$$; e.g. the following syntax is supported: $codei% static_cast( %x%[%i%] ) %$$ $lnext $icode elementType$$ supports the assignment operator $code =$$ where the right hand side is a $code bool$$ or an $icode elementType$$ object; e.g., if $icode y$$ has type $code bool$$, the following syntax is supported: $codei% %x%[%i%] = %y% %$$ $lnext The result of an assignment to an $icode elementType$$ also has type $icode elementType$$. Thus, if $icode z$$ has type $code bool$$, the following syntax is supported: $codei% %z% = %x%[%i%] = %y% %$$ $lend $head Memory and Parallel Mode$$ $index thread_alloc, vector$$ $index vector, thread_alloc$$ These vectors use the multi-threaded fast memory allocator $cref thread_alloc$$: $list number$$ The routine $cref/parallel_setup/ta_parallel_setup/$$ must be called before these vectors can be used $cref/in parallel/ta_in_parallel/$$. $lnext Using these vectors affects the amount of memory $cref/in_use/ta_inuse/$$ and $cref/available/ta_available/$$. $lnext Calling $cref/clear/CppAD_vector/clear/$$, makes the corresponding memory available (though $code thread_alloc$$) to the current thread. $lnext Available memory can then be completely freed using $cref/free_available/ta_free_available/$$. $lend $head Example$$ $children% example/cppad_vector.cpp% example/vector_bool.cpp %$$ The files $cref cppad_vector.cpp$$ and $cref vector_bool.cpp$$ each contain an example and test of this template class. They return true if they succeed and false otherwise. $head Exercise$$ $index exercise, CppAD::vector$$ Create and run a program that contains the following code: $codep CppAD::vector x(3); size_t i; for(i = 0; i < 3; i++) x[i] = 4. - i; Rcout << "x = " << x << std::endl; $$ $end $end ------------------------------------------------------------------------ */ # include # include # include # include # include # include namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file vector.hpp File used to define CppAD::vector and CppAD::vectorBool */ // --------------------------------------------------------------------------- /*! The CppAD Simple Vector template class. */ template class vector { private: /// maximum number of Type elements current allocation can hold size_t capacity_; /// number of Type elements currently in this vector size_t length_; /// pointer to the first type elements /// (not defined and should not be used when capacity_ = 0) Type * data_; public: /// type of the elements in the vector typedef Type value_type; /// default constructor sets capacity_ = length_ = data_ = 0 inline vector(void) : capacity_(0), length_(0), data_(CPPAD_NULL) { } /// sizing constructor inline vector( /// number of elements in this vector size_t n ) : capacity_(0), length_(n), data_(CPPAD_NULL) { if( length_ > 0 ) { // set capacity and data data_ = thread_alloc::create_array(length_, capacity_); } } /// copy constructor inline vector( /// the *this vector will be a copy of \c x const vector& x ) : capacity_(0), length_(x.length_), data_(CPPAD_NULL) { if( length_ > 0 ) { // set capacity and data data_ = thread_alloc::create_array(length_, capacity_); // copy values using assignment operator size_t i; for(i = 0; i < length_; i++) data_[i] = x.data_[i]; } } /// destructor ~vector(void) { if( capacity_ > 0 ) thread_alloc::delete_array(data_); } /// maximum number of elements current allocation can store inline size_t capacity(void) const { return capacity_; } /// number of elements currently in this vector. inline size_t size(void) const { return length_; } /// raw pointer to the data inline Type* data(void) { return data_; } /// const raw pointer to the data inline const Type* data(void) const { return data_; } /// change the number of elements in this vector. inline void resize( /// new number of elements for this vector size_t n ) { length_ = n; // check if we can use current memory if( capacity_ >= length_ ) return; // check if there is old memory to be freed if( capacity_ > 0 ) thread_alloc::delete_array(data_); // get new memory and set capacity data_ = thread_alloc::create_array(length_, capacity_); } /// free memory and set number of elements to zero inline void clear(void) { length_ = 0; // check if there is old memory to be freed if( capacity_ > 0 ) thread_alloc::delete_array(data_); capacity_ = 0; } /// vector assignment operator inline vector& operator=( /// right hand size of the assingment operation const vector& x ) { size_t i; // If original lenght is zero, then resize // otherwise a length mismatch is an error. if( length_ == 0 ) resize( x.length_ ); CPPAD_ASSERT_KNOWN( length_ == x.length_ , "vector: size miss match in assignment operation" ); for(i = 0; i < length_; i++) data_[i] = x.data_[i]; return *this; } # if CPPAD_HAS_RVALUE /// vector assignment operator with move semantics inline vector& operator=( /// right hand size of the assingment operation vector&& x ) { CPPAD_ASSERT_KNOWN( length_ == x.length_ || (length_ == 0), "vector: size miss match in assignment operation" ); if( this != &x ) { clear(); // length_ = x.length_; capacity_ = x.capacity_; data_ = x.data_; // x.length_ = 0; x.capacity_ = 0; x.data_ = CPPAD_NULL; } return *this; } # endif /// non-constant element access; i.e., we can change this element value Type& operator[]( /// element index, must be less than length size_t i ) { CPPAD_ASSERT_KNOWN( i < length_, "vector: index greater than or equal vector size" ); return data_[i]; } /// constant element access; i.e., we cannot change this element value const Type& operator[]( /// element index, must be less than length size_t i ) const { CPPAD_ASSERT_KNOWN( i < length_, "vector: index greater than or equal vector size" ); return data_[i]; } /// add an element to the back of this vector void push_back( /// value of the element const Type& s ) { CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ ); if( length_ + 1 > capacity_ ) { // store old capacity and data values size_t old_capacity = capacity_; Type* old_data = data_; // set new capacity and data values data_ = thread_alloc::create_array(length_ + 1, capacity_); // copy old data values size_t i; for(i = 0; i < length_; i++) data_[i] = old_data[i]; // free old data if( old_capacity > 0 ) thread_alloc::delete_array(old_data); } data_[length_++] = s; CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ ); } /*! add vector to the back of this vector (we could not use push_back becasue MS V++ 7.1 did not resolve to non-template member function when scalar is used.) */ template void push_vector( /// value of the vector that we are adding const Vector& v ) { CheckSimpleVector(); CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ ); size_t m = v.size(); size_t i; if( length_ + m > capacity_ ) { // store old capacity and data values size_t old_capacity = capacity_; Type* old_data = data_; // set new capacity and data values data_ = thread_alloc::create_array(length_ + m, capacity_); // copy old data values for(i = 0; i < length_; i++) data_[i] = old_data[i]; // free old data if( old_capacity > 0 ) thread_alloc::delete_array(old_data); } for(i = 0; i < m; i++) data_[length_++] = v[i]; CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ ); } }; /// output a vector template inline std::ostream& operator << ( /// stream to write the vector to std::ostream& os , /// vector that is output const CppAD::vector& vec ) { size_t i = 0; size_t n = vec.size(); os << "{ "; while(i < n) { os << vec[i++]; if( i < n ) os << ", "; } os << " }"; return os; } // --------------------------------------------------------------------------- /*! Class that is used to hold a non-constant element of a vector. */ class vectorBoolElement { /// the boolean data is packed with sizeof(UnitType) bits per value typedef size_t UnitType; private: /// pointer to the UnitType value holding this eleemnt UnitType* unit_; /// mask for the bit corresponding to this element /// (all zero except for bit that corresponds to this element) UnitType mask_; public: /// constructor from member values vectorBoolElement( /// unit for this element UnitType* unit , /// mask for this element UnitType mask ) : unit_(unit) , mask_(mask) { } /// constuctor from another element vectorBoolElement( /// other element const vectorBoolElement& e ) : unit_(e.unit_) , mask_(e.mask_) { } /// conversion to a boolean value operator bool() const { return (*unit_ & mask_) != 0; } /// assignment of this element to a bool vectorBoolElement& operator=( /// right hand side for assignment bool bit ) { if(bit) *unit_ |= mask_; else *unit_ &= ~mask_; return *this; } /// assignment of this element to another element vectorBoolElement& operator=(const vectorBoolElement& e) { if( *(e.unit_) & e.mask_ ) *unit_ |= mask_; else *unit_ &= ~mask_; return *this; } }; class vectorBool { /// the boolean data is packed with sizeof(UnitType) bits per value typedef size_t UnitType; private: /// number of bits packed into each UnitType value in data_ static const size_t bit_per_unit_ = std::numeric_limits::digits; /// number of UnitType values in data_ size_t n_unit_; /// number of bits currently stored in this vector size_t length_; /// pointer to where the bits are stored UnitType *data_; /// minimum number of UnitType values that can store length_ bits /// (note that this is really a function of length_) size_t unit_min(void) { if( length_ == 0 ) return 0; return (length_ - 1) / bit_per_unit_ + 1; } public: /// type corresponding to the elements of this vector /// (note that non-const elements actually use vectorBoolElement) typedef bool value_type; /// default constructor (sets all member data to zero) inline vectorBool(void) : n_unit_(0), length_(0), data_(CPPAD_NULL) { } /// sizing constructor inline vectorBool( /// number of bits in this vector size_t n ) : n_unit_(0), length_(n), data_(CPPAD_NULL) { if( length_ > 0 ) { // set n_unit and data size_t min_unit = unit_min(); data_ = thread_alloc::create_array(min_unit, n_unit_); } } /// copy constructor inline vectorBool( /// the *this vector will be a copy of \c v const vectorBool& v ) : n_unit_(0), length_(v.length_), data_(CPPAD_NULL) { if( length_ > 0 ) { // set n_unit and data size_t min_unit = unit_min(); data_ = thread_alloc::create_array(min_unit, n_unit_); // copy values using UnitType assignment operator CPPAD_ASSERT_UNKNOWN( min_unit <= v.n_unit_ ); size_t i; for(i = 0; i < min_unit; i++) data_[i] = v.data_[i]; } } /// destructor ~vectorBool(void) { if( n_unit_ > 0 ) thread_alloc::delete_array(data_); } /// number of elements in this vector inline size_t size(void) const { return length_; } /// maximum number of elements current allocation can store inline size_t capacity(void) const { return n_unit_ * bit_per_unit_; } /// change number of elements in this vector inline void resize( /// new number of elements for this vector size_t n ) { length_ = n; // check if we can use the current memory size_t min_unit = unit_min(); if( n_unit_ >= min_unit ) return; // check if there is old memory to be freed if( n_unit_ > 0 ) thread_alloc::delete_array(data_); // get new memory and set n_unit data_ = thread_alloc::create_array(min_unit, n_unit_); } /// free memory and set number of elements to zero inline void clear(void) { length_ = 0; // check if there is old memory to be freed if( n_unit_ > 0 ) thread_alloc::delete_array(data_); n_unit_ = 0; } /// vector assignment operator inline vectorBool& operator=( /// right hand size of the assingment operation const vectorBool& v ) { size_t i; CPPAD_ASSERT_KNOWN( length_ == v.length_ , "vectorBool: size miss match in assignment operation" ); size_t min_unit = unit_min(); CPPAD_ASSERT_UNKNOWN( min_unit <= n_unit_ ); CPPAD_ASSERT_UNKNOWN( min_unit <= v.n_unit_ ); for(i = 0; i < min_unit; i++) data_[i] = v.data_[i]; return *this; } # if CPPAD_HAS_RVALUE /// vector assignment operator with move semantics inline vectorBool& operator=( /// right hand size of the assingment operation vectorBool&& x ) { if( this != &x ) { clear(); // length_ = x.length_; n_unit_ = x.n_unit_; data_ = x.data_; // x.length_ = 0; x.n_unit_ = 0; x.data_ = CPPAD_NULL; } return *this; } # endif /// non-constant element access; i.e., we can change this element value vectorBoolElement operator[]( /// element index, must be less than length size_t k ) { size_t i, j; CPPAD_ASSERT_KNOWN( k < length_, "vectorBool: index greater than or equal vector size" ); i = k / bit_per_unit_; j = k - i * bit_per_unit_; return vectorBoolElement(data_ + i , UnitType(1) << j ); } /// constant element access; i.e., we cannot change this element value bool operator[](size_t k) const { size_t i, j; UnitType unit, mask; CPPAD_ASSERT_KNOWN( k < length_, "vectorBool: index greater than or equal vector size" ); i = k / bit_per_unit_; j = k - i * bit_per_unit_; unit = data_[i]; mask = UnitType(1) << j; return (unit & mask) != 0; } /// add an element to the back of this vector void push_back( /// value of the element bool bit ) { CPPAD_ASSERT_UNKNOWN( unit_min() <= n_unit_ ); size_t i, j; UnitType mask; if( length_ + 1 > n_unit_ * bit_per_unit_ ) { CPPAD_ASSERT_UNKNOWN( unit_min() == n_unit_ ); // store old n_unit and data values size_t old_n_unit = n_unit_; UnitType* old_data = data_; // set new n_unit and data values data_ = thread_alloc::create_array(n_unit_+1, n_unit_); // copy old data values for(i = 0; i < old_n_unit; i++) data_[i] = old_data[i]; // free old data if( old_n_unit > 0 ) thread_alloc::delete_array(old_data); } i = length_ / bit_per_unit_; j = length_ - i * bit_per_unit_; mask = UnitType(1) << j; if( bit ) data_[i] |= mask; else data_[i] &= ~mask; length_++; } /// add vector to the back of this vector template void push_vector( /// value of the vector that we are adding const Vector& v ) { CheckSimpleVector(); size_t min_unit = unit_min(); CPPAD_ASSERT_UNKNOWN( length_ <= n_unit_ * bit_per_unit_ ); // some temporaries size_t i, j, k, ell; UnitType mask; bool bit; // store old length size_t old_length = length_; // new length and minium number of units; length_ = length_ + v.size(); min_unit = unit_min(); if( length_ >= n_unit_ * bit_per_unit_ ) { // store old n_unit and data value size_t old_n_unit = n_unit_; UnitType* old_data = data_; // set new n_unit and data values data_ = thread_alloc::create_array(min_unit, n_unit_); // copy old data values for(i = 0; i < old_n_unit; i++) data_[i] = old_data[i]; // free old data if( old_n_unit > 0 ) thread_alloc::delete_array(old_data); } ell = old_length; for(k = 0; k < v.size(); k++) { i = ell / bit_per_unit_; j = ell - i * bit_per_unit_; bit = v[k]; mask = UnitType(1) << j; if( bit ) data_[i] |= mask; else data_[i] &= ~mask; ell++; } CPPAD_ASSERT_UNKNOWN( length_ == ell ); CPPAD_ASSERT_UNKNOWN( length_ <= n_unit_ * bit_per_unit_ ); } }; /// output a vector inline std::ostream& operator << ( /// steam to write the vector to std::ostream& os , /// vector that is output const vectorBool& v ) { size_t i = 0; size_t n = v.size(); while(i < n) os << v[i++]; return os; } } // END_CPPAD_NAMESPACE # endif TMB/inst/include/cppad/OdeGearControl.h0000644000176200001440000000006214113627761017411 0ustar liggesusers/* $Id$ */ # include "cppad/ode_gear_control.hpp" TMB/inst/include/cppad/speed/0000755000176200001440000000000014536067013015470 5ustar liggesusersTMB/inst/include/cppad/speed/det_33.hpp0000644000176200001440000000572114536067013017267 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DET_33_INCLUDED # define CPPAD_DET_33_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin det_33$$ $spell cppad CppAD det cppad.hpp namespace const bool $$ $section Check Determinant of 3 by 3 matrix$$ $index det_33$$ $index determinant, check correct$$ $index correct, determinant check$$ $index check, determinant correct$$ $head Syntax$$ $codei%# include %$$ $icode%ok% = det_33(%x%, %d%)%$$ $head Purpose$$ This routine can be used to check a method for computing the determinant of a matrix. $head Inclusion$$ The template function $code det_33$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/det_33.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$. It contains the elements of the matrix $latex X$$ in row major order; i.e., $latex \[ X_{i,j} = x [ i * 3 + j ] \] $$ $head d$$ The argument $icode d$$ has prototype $codei% const %Vector% &%d% %$$. It is tested to see if $icode%d%[0]%$$ it is equal to $latex \det ( X )$$. $head Vector$$ If $icode y$$ is a $icode Vector$$ object, it must support the syntax $codei% %y%[%i%] %$$ where $icode i$$ has type $code size_t$$ with value less than 9. This must return a $code double$$ value corresponding to the $th i$$ element of the vector $icode y$$. This is the only requirement of the type $icode Vector$$. (Note that only the first element of the vector $icode d$$ is used.) $head ok$$ The return value $icode ok$$ has prototype $codei% bool %ok% %$$ It is true, if the determinant $icode%d%[0]%$$ passes the test and false otherwise. $children% omh/det_33_hpp.omh %$$ $head Source Code$$ The file $cref det_33.hpp$$ contains the source code for this template function. $end ------------------------------------------------------------------------------ */ // BEGIN C++ # include namespace CppAD { template bool det_33(const Vector &x, const Vector &d) { bool ok = true; // use expansion by minors to compute the determinant by hand double check = 0.; check += x[0] * ( x[4] * x[8] - x[5] * x[7] ); check -= x[1] * ( x[3] * x[8] - x[5] * x[6] ); check += x[2] * ( x[3] * x[7] - x[4] * x[6] ); ok &= CppAD::NearEqual(check, d[0], 1e-10, 1e-10); return ok; } } // END C++ # endif TMB/inst/include/cppad/speed/uniform_01.hpp0000644000176200001440000000527414536067013020170 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_UNIFORM_01_INCLUDED # define CPPAD_UNIFORM_01_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin uniform_01$$ $spell CppAD cppad.hpp namespace $$ $section Simulate a [0,1] Uniform Random Variate$$ $index uniform_01$$ $index random, uniform vector$$ $index uniform, random vector$$ $index vector, uniform random$$ $head Syntax$$ $codei%# include %$$ $codei%uniform_01(%seed%) %$$ $codei%uniform_01(%n%, %x%)%$$ $head Purpose$$ This routine is used to create random values for speed testing purposes. $head Inclusion$$ The template function $code uniform_01$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/uniform_01.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head seed$$ The argument $icode seed$$ has prototype $codei% size_t %seed% %$$ It specifies a seed for the uniform random number generator. $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ It specifies the number of elements in the random vector $icode x$$. $head x$$ The argument $icode x$$ has prototype $codei% %Vector% &%x% %$$. The input value of the elements of $icode x$$ does not matter. Upon return, the elements of $icode x$$ are set to values randomly sampled over the interval [0,1]. $head Vector$$ If $icode y$$ is a $code double$$ value, the object $icode x$$ must support the syntax $codei% %x%[%i%] = %y% %$$ where $icode i$$ has type $code size_t$$ with value less than or equal $latex n-1$$. This is the only requirement of the type $icode Vector$$. $children% omh/uniform_01_hpp.omh %$$ $head Source Code$$ The file $cref uniform_01.hpp$$ constraints the source code for this template function. $end ------------------------------------------------------------------------------ */ // BEGIN C++ # include namespace CppAD { inline void uniform_01(size_t seed) { std::srand( (unsigned int) seed); } template void uniform_01(size_t n, Vector &x) { static double factor = 1. / double(RAND_MAX); while(n--) x[n] = std::rand() * factor; } } // END C++ # endif TMB/inst/include/cppad/speed/det_grad_33.hpp0000644000176200001440000000654314536067013020267 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DET_GRAD_33_INCLUDED # define CPPAD_DET_GRAD_33_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin det_grad_33$$ $spell cppad CppAD det cppad.hpp namespace const bool $$ $section Check Gradient of Determinant of 3 by 3 matrix$$ $index det_grad_33$$ $index determinant, check correct$$ $index correct, determinant check$$ $index check, determinant correct$$ $head Syntax$$ $codei%# include %$$ $icode%ok% = det_grad_33(%x%, %g%)%$$ $head Purpose$$ This routine can be used to check a method for computing the gradient of the determinant of a matrix. $head Inclusion$$ The template function $code det_grad_33$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/det_grad_33.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$. It contains the elements of the matrix $latex X$$ in row major order; i.e., $latex \[ X_{i,j} = x [ i * 3 + j ] \] $$ $head g$$ The argument $icode g$$ has prototype $codei% const %Vector% &%g% %$$. It contains the elements of the gradient of $latex \det ( X )$$ in row major order; i.e., $latex \[ \D{\det (X)}{X(i,j)} = g [ i * 3 + j ] \] $$ $head Vector$$ If $icode y$$ is a $icode Vector$$ object, it must support the syntax $codei% %y%[%i%] %$$ where $icode i$$ has type $code size_t$$ with value less than 9. This must return a $code double$$ value corresponding to the $th i$$ element of the vector $icode y$$. This is the only requirement of the type $icode Vector$$. $head ok$$ The return value $icode ok$$ has prototype $codei% bool %ok% %$$ It is true, if the gradient $icode g$$ passes the test and false otherwise. $children% omh/det_grad_33_hpp.omh %$$ $head Source Code$$ The file $cref det_grad_33.hpp$$ contains the source code for this template function. $end ------------------------------------------------------------------------------ */ // BEGIN C++ # include namespace CppAD { template bool det_grad_33(const Vector &x, const Vector &g) { bool ok = true; // use expansion by minors to compute the derivative by hand double check[9]; check[0] = + ( x[4] * x[8] - x[5] * x[7] ); check[1] = - ( x[3] * x[8] - x[5] * x[6] ); check[2] = + ( x[3] * x[7] - x[4] * x[6] ); // check[3] = - ( x[1] * x[8] - x[2] * x[7] ); check[4] = + ( x[0] * x[8] - x[2] * x[6] ); check[5] = - ( x[0] * x[7] - x[1] * x[6] ); // check[6] = + ( x[1] * x[5] - x[2] * x[4] ); check[7] = - ( x[0] * x[5] - x[2] * x[3] ); check[8] = + ( x[0] * x[4] - x[1] * x[3] ); // size_t i; for(i = 0; i < 3 * 3; i++) ok &= CppAD::NearEqual(check[i], g[i], 1e-10, 1e-10); return ok; } } // END C++ # endif TMB/inst/include/cppad/speed/det_by_lu.hpp0000644000176200001440000001076614536067013020161 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DET_BY_LU_INCLUDED # define CPPAD_DET_BY_LU_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin det_by_lu$$ $spell CppAD cppad lu hpp typedef const hpp Det CPPAD_TESTVECTOR namespace $$ $section Determinant Using Expansion by Lu Factorization$$ $index det_by_lu$$ $index determinant, lu factor$$ $index lu, factor determinant$$ $index factor, lu determinant$$ $head Syntax$$ $codei%# include %$$ $codei%det_by_lu<%Scalar%> %det%(%n%) %$$ $icode%d% = %det%(%a%) %$$ $head Inclusion$$ The template class $code det_by_lu$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/det_by_lu.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head Constructor$$ The syntax $codei% det_by_lu<%Scalar%> %det%(%n%) %$$ constructs the object $icode det$$ which can be used for evaluating the determinant of $icode n$$ by $icode n$$ matrices using LU factorization. $head Scalar$$ The type $icode Scalar$$ can be any $cref NumericType$$ $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ $head det$$ The syntax $codei% %d% = %det%(%a%) %$$ returns the determinant of the matrix $latex A$$ using LU factorization. $subhead a$$ The argument $icode a$$ has prototype $codei% const %Vector% &%a% %$$ It must be a $icode Vector$$ with length $latex n * n$$ and with It must be a $icode Vector$$ with length $latex n * n$$ and with elements of type $icode Scalar$$. The elements of the $latex n \times n$$ matrix $latex A$$ are defined, for $latex i = 0 , \ldots , n-1$$ and $latex j = 0 , \ldots , n-1$$, by $latex \[ A_{i,j} = a[ i * m + j] \] $$ $subhead d$$ The return value $icode d$$ has prototype $codei% %Scalar% %d% %$$ $head Vector$$ If $icode y$$ is a $icode Vector$$ object, it must support the syntax $codei% %y%[%i%] %$$ where $icode i$$ has type $code size_t$$ with value less than $latex n * n$$. This must return a $icode Scalar$$ value corresponding to the $th i$$ element of the vector $icode y$$. This is the only requirement of the type $icode Vector$$. $children% speed/example/det_by_lu.cpp% omh/det_by_lu_hpp.omh %$$ $head Example$$ The file $cref det_by_lu.cpp$$ contains an example and test of $code det_by_lu.hpp$$. It returns true if it succeeds and false otherwise. $head Source Code$$ The file $cref det_by_lu.hpp$$ contains the source for this template function. $end --------------------------------------------------------------------------- */ // BEGIN C++ # include # include // BEGIN CppAD namespace namespace CppAD { // The AD complex case is used by examples by not used by speed tests // Must define a specializatgion of LeqZero,AbsGeq for the ADComplex case typedef std::complex Complex; typedef CppAD::AD ADComplex; CPPAD_BOOL_UNARY(Complex, LeqZero ) CPPAD_BOOL_BINARY(Complex, AbsGeq ) template class det_by_lu { private: const size_t m_; const size_t n_; CPPAD_TESTVECTOR(Scalar) A_; CPPAD_TESTVECTOR(Scalar) B_; CPPAD_TESTVECTOR(Scalar) X_; public: det_by_lu(size_t n) : m_(0), n_(n), A_(n * n) { } template inline Scalar operator()(const Vector &x) { using CppAD::exp; Scalar logdet; Scalar det; int signdet; size_t i; // copy matrix so it is not overwritten for(i = 0; i < n_ * n_; i++) A_[i] = x[i]; // comput log determinant signdet = CppAD::LuSolve( n_, m_, A_, B_, X_, logdet); /* // Do not do this for speed test because it makes floating // point operation sequence very simple. if( signdet == 0 ) det = 0; else det = Scalar( signdet ) * exp( logdet ); */ // convert to determinant det = Scalar( signdet ) * exp( logdet ); # ifdef FADBAD // Fadbad requires tempories to be set to constants for(i = 0; i < n_ * n_; i++) A_[i] = 0; # endif return det; } }; } // END CppAD namespace // END C++ # endif TMB/inst/include/cppad/speed/mat_sum_sq.hpp0000644000176200001440000000720514536067013020355 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_MAT_SUM_SQ_INCLUDED # define CPPAD_MAT_SUM_SQ_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin mat_sum_sq$$ $spell sq namespace const CppAD sq cppad.hpp $$ $section Sum Elements of a Matrix Times Itself$$ $index mat_sum_sq$$ $index matrix, multiply speed test$$ $index speed, matrix multiply test$$ $index multiply, matrix speed test$$ $index test, matrix multiply speed$$ $head Syntax$$ $codei%# include %$$ $icode%mat_sum_sq(%n%, %x%, %y%, %z%)%$$ $head Purpose$$ This routine is intended for use with the matrix multiply speed tests; to be specific, it computes $latex \[ \begin{array}{rcl} y_{i,j} & = & \sum_{k=0}^{n-1} x_{i,k} x_{k,j} \\ z_0 & = & \sum_{i=0}^{n-1} \sum_{j=0}^{n-1} y_{i,j} \end{array} \] $$ see $cref link_mat_mul$$. $head Inclusion$$ The template function $code mat_sum_sq$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/mat_sum_sq.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head n$$ This argument has prototype $codei% size_t %n% %$$ It specifies the size of the matrices. $head x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ and $icode%x%.size() == %n% * %n%$$. It contains the elements of $latex x$$ in row major order; i.e., $latex \[ x_{i,j} = x [ i * n + j ] \] $$ $head y$$ The argument $icode y$$ has prototype $codei% %Vector%& %y% %$$ and $icode%y%.size() == %n% * %n%$$. The input value of its elements does not matter. Upon return, $latex \[ \begin{array}{rcl} y_{i,j} & = & \sum_{k=0}^{n-1} x_{i,k} x_{k,j} \\ y[ i * n + j ] & = & y_{i,j} \end{array} \] $$ $head z$$ The argument $icode d$$ has prototype $codei% %Vector%& %z% %$$. The input value of its element does not matter. Upon return $latex \[ \begin{array}{rcl} z_0 & = & \sum_{i=0}^{n-1} \sum_{j=0}^n y_{i,j} \\ z[0] & = & z_0 \end{array} \] $$ $head Vector$$ The type $icode Vector$$ is any $cref SimpleVector$$, or it can be a raw pointer to the vector elements. The element type must support addition, multiplication, and assignment to both its own type and to a double value. $children% speed/example/mat_sum_sq.cpp% omh/mat_sum_sq_hpp.omh %$$ $head Example$$ The file $cref mat_sum_sq.cpp$$ contains an example and test of $code mat_sum_sq.hpp$$. It returns true if it succeeds and false otherwise. $head Source Code$$ The file $cref mat_sum_sq.hpp$$ contains the source for this template function. $end ------------------------------------------------------------------------------ */ // BEGIN C++ # include // namespace CppAD { template void mat_sum_sq(size_t n, Vector& x , Vector& y , Vector& z) { size_t i, j, k; // Very simple computation of y = x * x for speed comparison for(i = 0; i < n; i++) { for(j = 0; j < n; j++) { y[i * n + j] = 0.; for(k = 0; k < n; k++) y[i * n + j] += x[i * n + k] * x[k * n + j]; } } z[0] = 0.; for(i = 0; i < n; i++) { for(j = 0; j < n; j++) z[0] += y[i * n + j]; } return; } } // END C++ # endif TMB/inst/include/cppad/speed/sparse_jac_fun.hpp0000644000176200001440000001347114536067013021171 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_JAC_FUN_INCLUDED # define CPPAD_SPARSE_JAC_FUN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin sparse_jac_fun$$ $spell Jacobian jac cppad hpp fp CppAD namespace const bool exp arg $$ $section Evaluate a Function That Has a Sparse Jacobian$$ $index sparse_jac_fun, function$$ $index function, sparse_jac_fun$$ $head Syntax$$ $codei%# include %$$ $codei%sparse_jac_fun(%m%, %n%, %x%, %row%, %col%, %p%, %fp%)%$$ $head Purpose$$ This routine evaluates $latex f(x)$$ and $latex f^{(1)} (x)$$ where the Jacobian $latex f^{(1)} (x)$$ is sparse. The function $latex f : \B{R}^n \rightarrow \B{R}^m$$ only depends on the size and contents of the index vectors $icode row$$ and $icode col$$. The non-zero entries in the Jacobian of this function have one of the following forms: $latex \[ \D{ f[row[k]]}{x[col[k]]} \] $$ for some $latex k $$ between zero and $latex K-1$$. All the other terms of the Jacobian are zero. $head Inclusion$$ The template function $code sparse_jac_fun$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/sparse_jac_fun.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head Float$$ The type $icode Float$$ must be a $cref NumericType$$. In addition, if $icode y$$ and $icode z$$ are $icode Float$$ objects, $codei% %y% = exp(%z%) %$$ must set the $icode y$$ equal the exponential of $icode z$$, i.e., the derivative of $icode y$$ with respect to $icode z$$ is equal to $icode y$$. $head FloatVector$$ The type $icode FloatVector$$ is any $cref SimpleVector$$, or it can be a raw pointer, with elements of type $icode Float$$. $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ It specifies the dimension for the domain space for $latex f(x)$$. $head m$$ The argument $icode m$$ has prototype $codei% size_t %m% %$$ It specifies the dimension for the range space for $latex f(x)$$. $head x$$ The argument $icode x$$ has prototype $codei% const %FloatVector%& %x% %$$ It contains the argument value for which the function, or its derivative, is being evaluated. We use $latex n$$ to denote the size of the vector $icode x$$. $head row$$ The argument $icode row$$ has prototype $codei% const CppAD::vector& %row% %$$ It specifies indices in the range of $latex f(x)$$ for non-zero components of the Jacobian (see $cref/purpose/sparse_hes_fun/Purpose/$$ above). The value $latex K$$ is defined by $icode%K% = %row%.size()%$$. All the elements of $icode row$$ must be between zero and $icode%m%-1%$$. $head col$$ The argument $icode row$$ has prototype $codei% const CppAD::vector& %col% %$$ and its size must be $latex K$$; i.e., the same as for $icode col$$. It specifies the component of $latex x$$ for the non-zero Jacobian terms. All the elements of $icode col$$ must be between zero and $icode%n%-1%$$. $head p$$ The argument $icode p$$ has prototype $codei% size_t %p% %$$ It is either zero or one and specifies the order of the derivative of $latex f$$ that is being evaluated, i.e., $latex f^{(p)} (x)$$ is evaluated. $head fp$$ The argument $icode fp$$ has prototype $codei% %FloatVector%& %fp% %$$ If $icode%p% = 0%$$, it size is $icode m$$ otherwise its size is $icode K$$. The input value of the elements of $icode fp$$ does not matter. $subhead Function$$ If $icode p$$ is zero, $icode fp$$ has size $latex m$$ and $codei%(%fp%[0]%, ... , %fp%[%m%-1])%$$ is the value of $latex f(x)$$. $subhead Jacobian$$ If $icode p$$ is one, $icode fp$$ has size $icode K$$ and for $latex k = 0 , \ldots , K-1$$, $latex \[ \D{f[ \R{row}[i] ]}{x[ \R{col}[j] ]} = fp [k] \] $$ $children% speed/example/sparse_jac_fun.cpp% omh/sparse_jac_fun.omh %$$ $head Example$$ The file $cref sparse_jac_fun.cpp$$ contains an example and test of $code sparse_jac_fun.hpp$$. It returns true if it succeeds and false otherwise. $head Source Code$$ The file $cref sparse_jac_fun.hpp$$ contains the source code for this template function. $end ------------------------------------------------------------------------------ */ // BEGIN C++ # include # include # include // following needed by gcc under fedora 17 so that exp(double) is defined # include namespace CppAD { template void sparse_jac_fun( size_t m , size_t n , const FloatVector& x , const CppAD::vector& row , const CppAD::vector& col , size_t p , FloatVector& fp ) { // check numeric type specifications CheckNumericType(); // check value of p CPPAD_ASSERT_KNOWN( p == 0 || p == 1, "sparse_jac_fun: p != 0 and p != 1" ); size_t K = row.size(); CPPAD_ASSERT_KNOWN( K >= m, "sparse_jac_fun: row.size() < m" ); size_t i, j, k; if( p == 0 ) for(i = 0; i < m; i++) fp[i] = Float(0); Float t; for(k = 0; k < K; k++) { i = row[k]; j = col[k]; t = exp( x[j] * x[j] / 2.0 ); switch(p) { case 0: fp[i] += t; break; case 1: fp[k] = t * x[j]; break; } } } } // END C++ # endif TMB/inst/include/cppad/speed/ode_evaluate.hpp0000644000176200001440000001402014536067013020633 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ODE_EVALUATE_INCLUDED # define CPPAD_ODE_EVALUATE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin ode_evaluate$$ $spell Runge fabs retaped Jacobian const Cpp cppad hpp fp namespace exp $$ $section Evaluate a Function Defined in Terms of an ODE$$ $index ode_evaluate, function$$ $index function, ode_evaluate$$ $head Syntax$$ $codei%# include %$$ $codei%ode_evaluate(%x%, %p%, %fp%)%$$ $head Purpose$$ This routine evaluates a function $latex f : \B{R}^n \rightarrow \B{R}^n$$ defined by $latex \[ f(x) = y(x, 1) \] $$ where $latex y(x, t)$$ solves the ordinary differential equation $latex \[ \begin{array}{rcl} y(x, 0) & = & x \\ \partial_t y (x, t ) & = & g[ y(x,t) , t ] \end{array} \] $$ where $latex g : \B{R}^n \times \B{R} \rightarrow \B{R}^n$$ is an unspecified function. $head Inclusion$$ The template function $code ode_evaluate$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/ode_evaluate.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head Float$$ $subhead Operation Sequence$$ The type $icode Float$$ must be a $cref NumericType$$. The $icode Float$$ $cref/operation sequence/glossary/Operation/Sequence/$$ for this routine does not depend on the value of the argument $icode x$$, hence it does not need to be retaped for each value of $latex x$$. $subhead fabs$$ If $icode y$$ and $icode z$$ are $icode Float$$ objects, the syntax $codei% %y% = fabs(%z%) %$$ must be supported. Note that it does not matter if the operation sequence for $code fabs$$ depends on $icode z$$ because the corresponding results are not actually used by $code ode_evaluate$$; see $code fabs$$ in $cref/Runge45/Runge45/Scalar/fabs/$$. $head x$$ The argument $icode x$$ has prototype $codei% const CppAD::vector<%Float%>& %x% %$$ It contains he argument value for which the function, or its derivative, is being evaluated. The value $latex n$$ is determined by the size of the vector $icode x$$. $head p$$ The argument $icode p$$ has prototype $codei% size_t %p% %$$ $subhead p == 0$$ In this case a numerical method is used to solve the ode and obtain an accurate approximation for $latex y(x, 1)$$. This numerical method has a fixed that does not depend on $icode x$$. $subhead p = 1$$ In this case an analytic solution for the partial derivative $latex \partial_x y(x, 1)$$ is returned. $head fp$$ The argument $icode fp$$ has prototype $codei% CppAD::vector<%Float%>& %fp% %$$ The input value of the elements of $icode fp$$ does not matter. $subhead Function$$ If $icode p$$ is zero, $icode fp$$ has size equal to $latex n$$ and contains the value of $latex y(x, 1)$$. $subhead Gradient$$ If $icode p$$ is one, $icode fp$$ has size equal to $icode n^2$$ and for $latex i = 0 , \ldots and n-1$$, $latex j = 0 , \ldots , n-1$$ $latex \[ \D{y[i]}{x[j]} (x, 1) = fp [ i \cdot n + j ] \] $$ $children% speed/example/ode_evaluate.cpp% omh/ode_evaluate.omh %$$ $head Example$$ The file $cref ode_evaluate.cpp$$ contains an example and test of $code ode_evaluate.hpp$$. It returns true if it succeeds and false otherwise. $head Source Code$$ The file $cref ode_evaluate.hpp$$ contains the source code for this template function. $end */ // BEGIN C++ # include # include # include namespace CppAD { template class ode_evaluate_fun { public: // Given that y_i (0) = x_i, // the following y_i (t) satisfy the ODE below: // y_0 (t) = x[0] // y_1 (t) = x[1] + x[0] * t // y_2 (t) = x[2] + x[1] * t + x[0] * t^2/2 // y_3 (t) = x[3] + x[2] * t + x[1] * t^2/2 + x[0] * t^3 / 3! // ... void Ode( const Float& t, const CppAD::vector& y, CppAD::vector& f) { size_t n = y.size(); f[0] = 0.; for(size_t k = 1; k < n; k++) f[k] = y[k-1]; } }; // template void ode_evaluate( const CppAD::vector& x , size_t p , CppAD::vector& fp ) { using CppAD::vector; typedef vector VectorFloat; size_t n = x.size(); CPPAD_ASSERT_KNOWN( p == 0 || p == 1, "ode_evaluate: p is not zero or one" ); CPPAD_ASSERT_KNOWN( ((p==0) & (fp.size()==n)) || ((p==1) & (fp.size()==n*n)), "ode_evaluate: the size of fp is not correct" ); if( p == 0 ) { // function that defines the ode ode_evaluate_fun F; // number of Runge45 steps to use size_t M = 10; // initial and final time Float ti = 0.0; Float tf = 1.0; // initial value for y(x, t); i.e. y(x, 0) // (is a reference to x) const VectorFloat& yi = x; // final value for y(x, t); i.e., y(x, 1) // (is a reference to fp) VectorFloat& yf = fp; // Use fourth order Runge-Kutta to solve ODE yf = CppAD::Runge45(F, M, ti, tf, yi); return; } /* Compute derivaitve of y(x, 1) w.r.t x y_0 (x, t) = x[0] y_1 (x, t) = x[1] + x[0] * t y_2 (x, t) = x[2] + x[1] * t + x[0] * t^2/2 y_3 (x, t) = x[3] + x[2] * t + x[1] * t^2/2 + x[0] * t^3 / 3! ... */ size_t i, j, k; for(i = 0; i < n; i++) { for(j = 0; j < n; j++) fp[ i * n + j ] = 0.0; } size_t factorial = 1; for(k = 0; k < n; k++) { if( k > 1 ) factorial *= k; for(i = k; i < n; i++) { // partial w.r.t x[i-k] of x[i-k] * t^k / k! j = i - k; fp[ i * n + j ] += 1.0 / Float(factorial); } } } } // END C++ # endif TMB/inst/include/cppad/speed/det_by_minor.hpp0000644000176200001440000000773414536067013020666 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DET_BY_MINOR_INCLUDED # define CPPAD_DET_BY_MINOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin det_by_minor$$ $spell CppAD cppad typedef const hpp Det namespace $$ $section Determinant Using Expansion by Minors$$ $index determinant, minor expansion$$ $index minor, expansion determinant$$ $index expansion, minor determinant$$ $head Syntax$$ $codei%# include %$$ $codei%det_by_minor<%Scalar%> %det%(%n%) %$$ $icode%d% = %det%(%a%) %$$ $head Inclusion$$ The template class $code det_by_minor$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/det_by_minor.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head Constructor$$ The syntax $codei% det_by_minor<%Scalar%> %det%(%n%) %$$ constructs the object $icode det$$ which can be used for evaluating the determinant of $icode n$$ by $icode n$$ matrices using expansion by minors. $head Scalar$$ The type $icode Scalar$$ must satisfy the same conditions as in the function $cref/det_of_minor/det_of_minor/Scalar/$$. $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ $head det$$ The syntax $codei% %d% = %det%(%a%) %$$ returns the determinant of the matrix $icode A$$ using expansion by minors. $subhead a$$ The argument $icode a$$ has prototype $codei% const %Vector% &%a% %$$ It must be a $icode Vector$$ with length $latex n * n$$ and with elements of type $icode Scalar$$. The elements of the $latex n \times n$$ matrix $latex A$$ are defined, for $latex i = 0 , \ldots , n-1$$ and $latex j = 0 , \ldots , n-1$$, by $latex \[ A_{i,j} = a[ i * m + j] \] $$ $subhead d$$ The return value $icode d$$ has prototype $codei% %Scalar% %d% %$$ It is equal to the determinant of $latex A$$. $head Vector$$ If $icode y$$ is a $icode Vector$$ object, it must support the syntax $codei% %y%[%i%] %$$ where $icode i$$ has type $code size_t$$ with value less than $latex n * n$$. This must return a $icode Scalar$$ value corresponding to the $th i$$ element of the vector $icode y$$. This is the only requirement of the type $icode Vector$$. $children% speed/example/det_by_minor.cpp% omh/det_by_minor_hpp.omh %$$ $head Example$$ The file $cref det_by_minor.cpp$$ contains an example and test of $code det_by_minor.hpp$$. It returns true if it succeeds and false otherwise. $head Source Code$$ The file $cref det_by_minor.hpp$$ contains the source for this template function. $end --------------------------------------------------------------------------- */ // BEGIN C++ # include # include // BEGIN CppAD namespace namespace CppAD { template class det_by_minor { private: size_t m_; // made mutable because modified and then restored mutable std::vector r_; mutable std::vector c_; // make mutable because its value does not matter mutable std::vector a_; public: det_by_minor(size_t m) : m_(m) , r_(m + 1) , c_(m + 1), a_(m * m) { size_t i; // values for r and c that correspond to entire matrix for(i = 0; i < m; i++) { r_[i] = i+1; c_[i] = i+1; } r_[m] = 0; c_[m] = 0; } template inline Scalar operator()(const Vector &x) const { size_t i = m_ * m_; while(i--) a_[i] = x[i]; return det_of_minor(a_, m_, m_, r_, c_); } }; } // END CppAD namespace // END C++ # endif TMB/inst/include/cppad/speed/sparse_hes_fun.hpp0000644000176200001440000001563114536067013021213 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPARSE_HES_FUN_INCLUDED # define CPPAD_SPARSE_HES_FUN_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin sparse_hes_fun$$ $spell hes cppad hpp fp CppAD namespace const bool exp arg $$ $section Evaluate a Function That Has a Sparse Hessian$$ $index sparse_hes_fun, function$$ $index function, sparse_hes_fun$$ $head Syntax$$ $codei%# include %$$ $codei%sparse_hes_fun(%n%, %x%, %row%, %col%, %p%, %fp%)%$$ $head Purpose$$ This routine evaluates $latex f(x)$$, $latex f^{(1)} (x)$$, or $latex f^{(2)} (x)$$ where the Hessian $latex f^{(2)} (x)$$ is sparse. The function $latex f : \B{R}^n \rightarrow \B{R}$$ only depends on the size and contents of the index vectors $icode row$$ and $icode col$$. The non-zero entries in the Hessian of this function have one of the following forms: $latex \[ \DD{f}{x[row[k]]}{x[row[k]]} \; , \; \DD{f}{x[row[k]]}{x[col[k]]} \; , \; \DD{f}{x[col[k]]}{x[row[k]]} \; , \; \DD{f}{x[col[k]]}{x[col[k]]} \] $$ for some $latex k $$ between zero and $latex K-1 $$. All the other terms of the Hessian are zero. $head Inclusion$$ The template function $code sparse_hes_fun$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/sparse_hes_fun.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head Float$$ The type $icode Float$$ must be a $cref NumericType$$. In addition, if $icode y$$ and $icode z$$ are $icode Float$$ objects, $codei% %y% = exp(%z%) %$$ must set the $icode y$$ equal the exponential of $icode z$$, i.e., the derivative of $icode y$$ with respect to $icode z$$ is equal to $icode y$$. $head FloatVector$$ The type $icode FloatVector$$ is any $cref SimpleVector$$, or it can be a raw pointer, with elements of type $icode Float$$. $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ It specifies the dimension for the domain space for $latex f(x)$$. $head x$$ The argument $icode x$$ has prototype $codei% const %FloatVector%& %x% %$$ It contains the argument value for which the function, or its derivative, is being evaluated. We use $latex n$$ to denote the size of the vector $icode x$$. $head row$$ The argument $icode row$$ has prototype $codei% const CppAD::vector& %row% %$$ It specifies one of the first index of $latex x$$ for each non-zero Hessian term (see $cref/purpose/sparse_hes_fun/Purpose/$$ above). All the elements of $icode row$$ must be between zero and $icode%n%-1%$$. The value $latex K$$ is defined by $icode%K% = %row%.size()%$$. $head col$$ The argument $icode col$$ has prototype $codei% const CppAD::vector& %col% %$$ and its size must be $latex K$$; i.e., the same as for $icode col$$. It specifies the second index of $latex x$$ for the non-zero Hessian terms. All the elements of $icode col$$ must be between zero and $icode%n%-1%$$. There are no duplicated entries requested, to be specific, if $icode%k1% != %k2%$$ then $codei% ( %row%[%k1%] , %col%[%k1%] ) != ( %row%[%k2%] , %col%[%k2%] ) %$$ $head p$$ The argument $icode p$$ has prototype $codei% size_t %p% %$$ It is either zero or two and specifies the order of the derivative of $latex f$$ that is being evaluated, i.e., $latex f^{(p)} (x)$$ is evaluated. $head fp$$ The argument $icode fp$$ has prototype $codei% %FloatVector%& %fp% %$$ The input value of the elements of $icode fp$$ does not matter. $subhead Function$$ If $icode p$$ is zero, $icode fp$$ has size one and $icode%fp%[0]%$$ is the value of $latex f(x)$$. $subhead Hessian$$ If $icode p$$ is two, $icode fp$$ has size $icode K$$ and for $latex k = 0 , \ldots , K-1$$, $latex \[ \DD{f}{ x[ \R{row}[k] ] }{ x[ \R{col}[k] ]} = fp [k] \] $$ $children% speed/example/sparse_hes_fun.cpp% omh/sparse_hes_fun.omh %$$ $head Example$$ The file $cref sparse_hes_fun.cpp$$ contains an example and test of $code sparse_hes_fun.hpp$$. It returns true if it succeeds and false otherwise. $head Source Code$$ The file $cref sparse_hes_fun.hpp$$ contains the source code for this template function. $end ------------------------------------------------------------------------------ */ // BEGIN C++ # include # include # include // following needed by gcc under fedora 17 so that exp(double) is defined # include namespace CppAD { template void sparse_hes_fun( size_t n , const FloatVector& x , const CppAD::vector& row , const CppAD::vector& col , size_t p , FloatVector& fp ) { // check numeric type specifications CheckNumericType(); // check value of p CPPAD_ASSERT_KNOWN( p == 0 || p == 2, "sparse_hes_fun: p != 0 and p != 2" ); size_t K = row.size(); size_t i, j, k; if( p == 0 ) fp[0] = Float(0); else { for(k = 0; k < K; k++) fp[k] = Float(0); } // determine which diagonal entries are present in row[k], col[k] CppAD::vector diagonal(n); for(i = 0; i < n; i++) diagonal[i] = K; // no diagonal entry for this row for(k = 0; k < K; k++) { if( row[k] == col[k] ) { CPPAD_ASSERT_UNKNOWN( diagonal[row[k]] == K ); // index of the diagonal entry diagonal[ row[k] ] = k; } } // determine which entries must be multiplied by a factor of two CppAD::vector factor(K); for(k = 0; k < K; k++) { factor[k] = Float(1); for(size_t k1 = 0; k1 < K; k1++) { bool reflected = true; reflected &= k != k1; reflected &= row[k] != col[k]; reflected &= row[k] == col[k1]; reflected &= col[k] == row[k1]; if( reflected ) factor[k] = Float(2); } } Float t; for(k = 0; k < K; k++) { i = row[k]; j = col[k]; t = exp( x[i] * x[j] ); switch(p) { case 0: fp[0] += t; break; case 2: if( i == j ) { // dt_dxi = 2.0 * xi * t fp[k] += ( Float(2) + Float(4) * x[i] * x[i] ) * t; } else { // dt_dxi = xj * t fp[k] += factor[k] * ( Float(1) + x[i] * x[j] ) * t; if( diagonal[i] != K ) { size_t ki = diagonal[i]; fp[ki] += x[j] * x[j] * t; } if( diagonal[j] != K ) { size_t kj = diagonal[j]; fp[kj] += x[i] * x[i] * t; } } break; } } } } // END C++ # endif TMB/inst/include/cppad/speed/det_of_minor.hpp0000644000176200001440000001646014536067013020654 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_DET_OF_MINOR_INCLUDED # define CPPAD_DET_OF_MINOR_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin det_of_minor$$ $spell CppAD cppad.hpp hpp std Det const namespace $$ $index det_of_minor$$ $index determinant, matrix minor$$ $index matrix, minor determinant$$ $index minor, matrix determinant$$ $section Determinant of a Minor$$ $head Syntax$$ $codei%# include %$$ $icode%d% = det_of_minor(%a%, %m%, %n%, %r%, %c%)%$$ $head Inclusion$$ The template function $code det_of_minor$$ is defined in the $code CppAD$$ namespace by including the file $code cppad/speed/det_of_minor.hpp$$ (relative to the CppAD distribution directory). It is only intended for example and testing purposes, so it is not automatically included by $cref/cppad.hpp/cppad/$$. $head Purpose$$ This template function returns the determinant of a minor of the matrix $latex A$$ using expansion by minors. The elements of the $latex n \times n$$ minor $latex M$$ of the matrix $latex A$$ are defined, for $latex i = 0 , \ldots , n-1$$ and $latex j = 0 , \ldots , n-1$$, by $latex \[ M_{i,j} = A_{R(i), C(j)} \]$$ where the functions $latex R(i)$$ is defined by the $cref/argument r/det_of_minor/r/$$ and $latex C(j)$$ is defined by the $cref/argument c/det_of_minor/c/$$. $pre $$ This template function is for example and testing purposes only. Expansion by minors is chosen as an example because it uses a lot of floating point operations yet does not require much source code (on the order of $icode m$$ factorial floating point operations and about 70 lines of source code including comments). This is not an efficient method for computing a determinant; for example, using an LU factorization would be better. $head Determinant of A$$ If the following conditions hold, the minor is the entire matrix $latex A$$ and hence $code det_of_minor$$ will return the determinant of $latex A$$: $list number$$ $latex n = m$$. $lnext for $latex i = 0 , \ldots , m-1$$, $latex r[i] = i+1$$, and $latex r[m] = 0$$. $lnext for $latex j = 0 , \ldots , m-1$$, $latex c[j] = j+1$$, and $latex c[m] = 0$$. $lend $head a$$ The argument $icode a$$ has prototype $codei% const std::vector<%Scalar%>& %a% %$$ and is a vector with size $latex m * m$$ (see description of $cref/Scalar/det_of_minor/Scalar/$$ below). The elements of the $latex m \times m$$ matrix $latex A$$ are defined, for $latex i = 0 , \ldots , m-1$$ and $latex j = 0 , \ldots , m-1$$, by $latex \[ A_{i,j} = a[ i * m + j] \] $$ $head m$$ The argument $icode m$$ has prototype $codei% size_t %m% %$$ and is the number of rows (and columns) in the square matrix $latex A$$. $head n$$ The argument $icode n$$ has prototype $codei% size_t %n% %$$ and is the number of rows (and columns) in the square minor $latex M$$. $head r$$ The argument $icode r$$ has prototype $codei% std::vector& %r% %$$ and is a vector with $latex m + 1$$ elements. This vector defines the function $latex R(i)$$ which specifies the rows of the minor $latex M$$. To be specific, the function $latex R(i)$$ for $latex i = 0, \ldots , n-1$$ is defined by $latex \[ \begin{array}{rcl} R(0) & = & r[m] \\ R(i+1) & = & r[ R(i) ] \end{array} \] $$ All the elements of $icode r$$ must have value less than or equal $icode m$$. The elements of vector $icode r$$ are modified during the computation, and restored to their original value before the return from $code det_of_minor$$. $head c$$ The argument $icode c$$ has prototype $codei% std::vector& %c% %$$ and is a vector with $latex m + 1$$ elements This vector defines the function $latex C(i)$$ which specifies the rows of the minor $latex M$$. To be specific, the function $latex C(i)$$ for $latex j = 0, \ldots , n-1$$ is defined by $latex \[ \begin{array}{rcl} C(0) & = & c[m] \\ C(j+1) & = & c[ C(j) ] \end{array} \] $$ All the elements of $icode c$$ must have value less than or equal $icode m$$. The elements of vector $icode c$$ are modified during the computation, and restored to their original value before the return from $code det_of_minor$$. $head d$$ The result $icode d$$ has prototype $codei% %Scalar% %d% %$$ and is equal to the determinant of the minor $latex M$$. $head Scalar$$ If $icode x$$ and $icode y$$ are objects of type $icode Scalar$$ and $icode i$$ is an object of type $code int$$, the $icode Scalar$$ must support the following operations: $table $bold Syntax$$ $cnext $bold Description$$ $cnext $bold Result Type$$ $rnext $icode%Scalar% %x%$$ $cnext default constructor for $icode Scalar$$ object. $rnext $icode%x% = %i%$$ $cnext set value of $icode x$$ to current value of $icode i$$ $rnext $icode%x% = %y%$$ $cnext set value of $icode x$$ to current value of $icode y$$ $rnext $icode%x% + %y%$$ $cnext value of $icode x$$ plus $icode y$$ $cnext $icode Scalar$$ $rnext $icode%x% - %y%$$ $cnext value of $icode x$$ minus $icode y$$ $cnext $icode Scalar$$ $rnext $icode%x% * %y%$$ $cnext value of $icode x$$ times value of $icode y$$ $cnext $icode Scalar$$ $tend $children% speed/example/det_of_minor.cpp% omh/det_of_minor_hpp.omh %$$ $head Example$$ The file $cref det_of_minor.cpp$$ contains an example and test of $code det_of_minor.hpp$$. It returns true if it succeeds and false otherwise. $head Source Code$$ The file $cref det_of_minor.hpp$$ contains the source for this template function. $end --------------------------------------------------------------------------- */ // BEGIN C++ namespace CppAD { // BEGIN CppAD namespace template Scalar det_of_minor( const std::vector& a , size_t m , size_t n , std::vector& r , std::vector& c ) { const size_t R0 = r[m]; // R(0) size_t Cj = c[m]; // C(j) (case j = 0) size_t Cj1 = m; // C(j-1) (case j = 0) // check for 1 by 1 case if( n == 1 ) return a[ R0 * m + Cj ]; // initialize determinant of the minor M Scalar detM = Scalar(0); // initialize sign of factor for next sub-minor int s = 1; // remove row with index 0 in M from all the sub-minors of M r[m] = r[R0]; // for each column of M for(size_t j = 0; j < n; j++) { // element with index (0,j) in the minor M Scalar M0j = a[ R0 * m + Cj ]; // remove column with index j in M to form next sub-minor S of M c[Cj1] = c[Cj]; // compute determinant of the current sub-minor S Scalar detS = det_of_minor(a, m, n - 1, r, c); // restore column Cj to representaion of M as a minor of A c[Cj1] = Cj; // include this sub-minor term in the summation if( s > 0 ) detM = detM + M0j * detS; else detM = detM - M0j * detS; // advance to next column of M Cj1 = Cj; Cj = c[Cj]; s = - s; } // restore row zero to the minor representation for M r[m] = R0; // return the determinant of the minor M return detM; } } // END CppAD namespace // END C++ # endif TMB/inst/include/cppad/romberg_mul.hpp0000644000176200001440000001744114536067013017422 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ROMBERG_MUL_INCLUDED # define CPPAD_ROMBERG_MUL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin RombergMul$$ $spell cppad.hpp bool const Cpp RombergMulMul $$ $section Multi-dimensional Romberg Integration$$ $index integrate, multi-dimensional Romberg$$ $index Romberg, multi-dimensional integrate$$ $index multi, dimensional Romberg integration$$ $index dimension, multi Romberg integration$$ $head Syntax$$ $code # include $$ $pre $$ $codei%RombergMul<%Fun%, %SizeVector%, %FloatVector%, %m%> %R%$$ $pre $$ $icode%r% = %R%(%F%, %a%, %b%, %n%, %p%, %e%)%$$ $head Description$$ Returns the Romberg integration estimate $latex r$$ for the multi-dimensional integral $latex \[ r = \int_{a[0]}^{b[0]} \cdots \int_{a[m-1]}^{b[m-1]} \; F(x) \; {\bf d} x_0 \cdots {\bf d} x_{m-1} \; + \; \sum_{i=0}^{m-1} O \left[ ( b[i] - a[i] ) / 2^{n[i]-1} \right]^{2(p[i]+1)} \] $$ $head Include$$ The file $code cppad/romberg_mul.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head m$$ The template parameter $icode m$$ must be convertible to a $code size_t$$ object with a value that can be determined at compile time; for example $code 2$$. It determines the dimension of the domain space for the integration. $head r$$ The return value $icode r$$ has prototype $codei% %Float% %r% %$$ It is the estimate computed by $code RombergMul$$ for the integral above (see description of $cref/Float/RombergMul/Float/$$ below). $head F$$ The object $icode F$$ has the prototype $codei% %Fun% &%F% %$$ It must support the operation $codei% %F%(%x%) %$$ The argument $icode x$$ to $icode F$$ has prototype $codei% const %Float% &%x% %$$ The return value of $icode F$$ is a $icode Float$$ object $head a$$ The argument $icode a$$ has prototype $codei% const %FloatVector% &%a% %$$ It specifies the lower limit for the integration (see description of $cref/FloatVector/RombergMul/FloatVector/$$ below). $head b$$ The argument $icode b$$ has prototype $codei% const %FloatVector% &%b% %$$ It specifies the upper limit for the integration. $head n$$ The argument $icode n$$ has prototype $codei% const %SizeVector% &%n% %$$ A total number of $latex 2^{n[i]-1} + 1$$ evaluations of $icode%F%(%x%)%$$ are used to estimate the integral with respect to $latex {\bf d} x_i$$. $head p$$ The argument $icode p$$ has prototype $codei% const %SizeVector% &%p% %$$ For $latex i = 0 , \ldots , m-1$$, $latex n[i]$$ determines the accuracy order in the approximation for the integral that is returned by $code RombergMul$$. The values in $icode p$$ must be less than or equal $icode n$$; i.e., $icode%p%[%i%] <= %n%[%i%]%$$. $head e$$ The argument $icode e$$ has prototype $codei% %Float% &%e% %$$ The input value of $icode e$$ does not matter and its output value is an approximation for the absolute error in the integral estimate. $head Float$$ The type $icode Float$$ is defined as the type of the elements of $cref/FloatVector/RombergMul/FloatVector/$$. The type $icode Float$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, if $icode x$$ and $icode y$$ are $icode Float$$ objects, $codei% %x% < %y% %$$ returns the $code bool$$ value true if $icode x$$ is less than $icode y$$ and false otherwise. $head FloatVector$$ The type $icode FloatVector$$ must be a $cref SimpleVector$$ class. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $children% example/romberg_mul.cpp %$$ $head Example$$ $comment% example/romberg_mul.cpp %$$ The file $cref Rombergmul.cpp$$ contains an example and test a test of using this routine. It returns true if it succeeds and false otherwise. $head Source Code$$ The source code for this routine is in the file $code cppad/romberg_mul.hpp$$. $end */ # include # include # include # include namespace CppAD { // BEGIN CppAD namespace template class SliceLast { typedef typename FloatVector::value_type Float; private: Fun *F; size_t last; FloatVector x; public: SliceLast( Fun *F_, size_t last_, const FloatVector &x_ ) : F(F_) , last(last_), x(last + 1) { size_t i; for(i = 0; i < last; i++) x[i] = x_[i]; } double operator()(const Float &xlast) { x[last] = xlast; return (*F)(x); } }; template class IntegrateLast { private: Fun *F; const size_t last; const FloatVector a; const FloatVector b; const SizeVector n; const SizeVector p; Float esum; size_t ecount; public: IntegrateLast( Fun *F_ , size_t last_ , const FloatVector &a_ , const FloatVector &b_ , const SizeVector &n_ , const SizeVector &p_ ) : F(F_) , last(last_), a(a_) , b(b_) , n(n_) , p(p_) { } Float operator()(const FloatVector &x) { Float r, e; SliceLast S(F, last, x); r = CppAD::RombergOne( S, a[last], b[last], n[last], p[last], e ); esum = esum + e; ecount++; return r; } void ClearEsum(void) { esum = 0.; } Float GetEsum(void) { return esum; } void ClearEcount(void) { ecount = 0; } size_t GetEcount(void) { return ecount; } }; template class RombergMul { typedef typename FloatVector::value_type Float; public: RombergMul(void) { } Float operator() ( Fun &F , const FloatVector &a , const FloatVector &b , const SizeVector &n , const SizeVector &p , Float &e ) { Float r; typedef IntegrateLast< Fun , SizeVector , FloatVector , Float > IntegrateOne; IntegrateOne Fm1(&F, m-1, a, b, n, p); RombergMul< IntegrateOne, SizeVector , FloatVector , m-1 > RombergMulM1; Fm1.ClearEsum(); Fm1.ClearEcount(); r = RombergMulM1(Fm1, a, b, n, p, e); size_t i, j; Float prod = 1; size_t pow2 = 1; CPPAD_UNUSED(pow2); for(i = 0; i < m-1; i++) { prod *= (b[i] - a[i]); for(j = 0; j < (n[i] - 1); j++) pow2 *= 2; } assert( Fm1.GetEcount() == (pow2+1) ); e = e + Fm1.GetEsum() * prod / Fm1.GetEcount(); return r; } }; template class RombergMul { typedef typename FloatVector::value_type Float; public: Float operator() ( Fun &F , const FloatVector &a , const FloatVector &b , const SizeVector &n , const SizeVector &p , Float &e ) { Float r; typedef IntegrateLast< Fun , SizeVector , FloatVector , Float > IntegrateOne; // check simple vector class specifications CheckSimpleVector(); // check numeric type specifications CheckNumericType(); IntegrateOne F0(&F, 0, a, b, n, p); F0.ClearEsum(); F0.ClearEcount(); r = F0(a); assert( F0.GetEcount() == 1 ); e = F0.GetEsum(); return r; } }; } // END CppAD namespace # endif TMB/inst/include/cppad/check_numeric_type.hpp0000644000176200001440000001236614536067012020750 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_CHECK_NUMERIC_TYPE_INCLUDED # define CPPAD_CHECK_NUMERIC_TYPE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin CheckNumericType$$ $spell alloc cppad.hpp CppAD $$ $section Check NumericType Class Concept$$ $index numeric, check$$ $index check, numeric$$ $index concept, check numeric$$ $head Syntax$$ $code # include $$ $pre $$ $codei%CheckNumericType<%NumericType%>()%$$ $head Purpose$$ The syntax $codei% CheckNumericType<%NumericType%>() %$$ preforms compile and run time checks that the type specified by $icode NumericType$$ satisfies all the requirements for a $cref NumericType$$ class. If a requirement is not satisfied, a an error message makes it clear what condition is not satisfied. $head Include$$ The file $code cppad/check_numeric_type.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest if the CppAD include files. $head Parallel Mode$$ $index parallel, CheckNumericType$$ $index CheckNumericType, parallel$$ The routine $cref/thread_alloc::parallel_setup/ta_parallel_setup/$$ must be called before it can be used in $cref/parallel/ta_in_parallel/$$ mode. $head Example$$ $children% example/check_numeric_type.cpp %$$ The file $cref check_numeric_type.cpp$$ contains an example and test of this function. It returns true, if it succeeds an false otherwise. The comments in this example suggest a way to change the example so an error message occurs. $end --------------------------------------------------------------------------- */ # include # include namespace CppAD { # ifdef NDEBUG template void CheckNumericType(void) { } # else template NumericType CheckNumericType(void) { // Section 3.6.2 of ISO/IEC 14882:1998(E) states: "The storage for // objects with static storage duration (3.7.1) shall be zero- // initialized (8.5) before any other initialization takes place." static size_t count[CPPAD_MAX_NUM_THREADS]; size_t thread = thread_alloc::thread_num(); if( count[thread] > 0 ) return NumericType(0); count[thread]++; /* contructors */ NumericType check_NumericType_default_constructor; NumericType check_NumericType_constructor_from_int(1); const NumericType x(1); NumericType check_NumericType_copy_constructor(x); // assignment NumericType check_NumericType_assignment; check_NumericType_assignment = x; /* unary operators */ const NumericType check_NumericType_unary_plus(1); NumericType check_NumericType_unary_plus_result = + check_NumericType_unary_plus; const NumericType check_NumericType_unary_minus(1); NumericType check_NumericType_unary_minus_result = - check_NumericType_unary_minus; /* binary operators */ const NumericType check_NumericType_binary_addition(1); NumericType check_NumericType_binary_addition_result = check_NumericType_binary_addition + x; const NumericType check_NumericType_binary_subtraction(1); NumericType check_NumericType_binary_subtraction_result = check_NumericType_binary_subtraction - x; const NumericType check_NumericType_binary_multiplication(1); NumericType check_NumericType_binary_multiplication_result = check_NumericType_binary_multiplication * x; const NumericType check_NumericType_binary_division(1); NumericType check_NumericType_binary_division_result = check_NumericType_binary_division / x; /* computed assignment operators */ NumericType check_NumericType_computed_assignment_addition(1); check_NumericType_computed_assignment_addition += x; NumericType check_NumericType_computed_assignment_subtraction(1); check_NumericType_computed_assignment_subtraction -= x; NumericType check_NumericType_computed_assignment_multiplication(1); check_NumericType_computed_assignment_multiplication *= x; NumericType check_NumericType_computed_assignment_division(1); check_NumericType_computed_assignment_division /= x; /* use all values so as to avoid warnings */ check_NumericType_default_constructor = x; return + check_NumericType_default_constructor + check_NumericType_constructor_from_int + check_NumericType_copy_constructor + check_NumericType_assignment + check_NumericType_unary_plus_result + check_NumericType_unary_minus_result + check_NumericType_binary_addition_result + check_NumericType_binary_subtraction_result + check_NumericType_binary_multiplication_result + check_NumericType_binary_division_result + check_NumericType_computed_assignment_addition + check_NumericType_computed_assignment_subtraction + check_NumericType_computed_assignment_multiplication + check_NumericType_computed_assignment_division ; } # endif } // end namespace CppAD # endif TMB/inst/include/cppad/RombergOne.h0000644000176200001440000000005514113627761016603 0ustar liggesusers/* $Id$ */ # include "cppad/romberg_one.hpp" TMB/inst/include/cppad/Poly.h0000644000176200001440000000004614113627761015467 0ustar liggesusers/* $Id$ */ # include "cppad/poly.hpp" TMB/inst/include/cppad/configure.hpp0000644000176200001440000001212314536067012017060 0ustar liggesusers// $Id:$ # ifndef CPPAD_CONFIGURE_INCLUDED # define CPPAD_CONFIGURE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin configure$$ $spell CppAD $$ $section Preprocessor Definitions Used by CppAD$$ $index configure, symbol$$ $index symbol, configure$$ $head Preprocessor Symbols$$ $index preprocessor, symbol$$ $index symbol, processor$$ All of the preprocessor symbols used by CppAD begin with $code CPPAD_$$ (there are some deprecated symbols that begin with $code CppAD$$). $end */ /*! \file configure.hpp Replacement for config.h so that all preprocessor symbols begin with CPPAD_ */ # if __cplusplus >= 201100 /*! \def CPPAD_HAS_RVALUE C++11: Does compiler cupport rvalues; i.e., values with move semantics */ # define CPPAD_HAS_RVALUE 0 # endif # if __cplusplus >= 201100 /*! def CPPAD_HAS_NULLPTR C++11: Does compiler support the null-pointer constant nullptr */ # define CPPAD_HAS_NULLPTR 0 # endif # if __cplusplus >= 201100 /*! \def CPPAD_HAS_CSTDINT_8_TO_64 C++11: Does compiler support the types uint_8, uint_16, uint_32, and uint_64 */ # define CPPAD_HAS_CSTDINT_8_TO_64 0 # endif # if __cplusplus >= 201100 /*! \def CPPAD_COMPILER_HAS_ERF C++11: Does compiler support std::erf(double) */ # define CPPAD_COMPILER_HAS_ERF 0 # endif # if __cplusplus >= 201100 /*! \def CPPAD_HAS_HIGH_RESOLUTION_CLOCK C++11: Does compiler support std::chrono::high_resolution_clock */ # define CPPAD_HAS_HIGH_RESOLUTION_CLOCK 0 # endif /*! \def CPPAD_PACKAGE_STRING cppad-yyyymmdd as a C string where yyyy is year, mm is month, and dd is day. */ # define CPPAD_PACKAGE_STRING "cppad-20141230" /*! def CPPAD_HAS_COLPACK Was a colpack_prefix specified on the cmake command line. */ # define CPPAD_HAS_COLPACK 0 /*! def CPPAD_INTERNAL_SPARSE_SET is the internal representation used for sparse vectors of std::set either sparse_set or sparse_list). */ # define CPPAD_INTERNAL_SPARSE_SET sparse_list /*! \def CPPAD_IMPLICIT_CTOR_FROM_ANY_TYPE If this symbol is one, an implicit constor of AD is defined where the argument has any type. Otherwise this constructor is explicit. */ # define CPPAD_IMPLICIT_CTOR_FROM_ANY_TYPE 0 /*! \def CPPAD_BOOSTVECTOR If this symbol is one, and _MSC_VER is not defined, we are using boost vector for CPPAD_TESTVECTOR. It this symbol is zero, we are not using boost vector for CPPAD_TESTVECTOR. */ # define CPPAD_BOOSTVECTOR 0 /*! \def CPPAD_CPPADVECTOR If this symbol is one, we are using CppAD vector for CPPAD_TESTVECTOR. It this symbol is zero, we are not using CppAD vector for CPPAD_TESTVECTOR. */ # define CPPAD_CPPADVECTOR 0 /*! \def CPPAD_STDVECTOR If this symbol is one, we are using standard vector for CPPAD_TESTVECTOR. It this symbol is zero, we are not using standard vector for CPPAD_TESTVECTOR. */ # define CPPAD_STDVECTOR 0 /*! \def CPPAD_EIGENVECTOR If this symbol is one, we are using Eigen vector for CPPAD_TESTVECTOR. If this symbol is zero, we are not using Eigen vector for CPPAD_TESTVECTOR. */ # define CPPAD_EIGENVECTOR 1 /*! \def CPPAD_HAS_GETTIMEOFDAY If this symbol is one, and _MSC_VER is not defined, this system supports the gettimeofday funcgtion. Otherwise, this smybol should be zero. */ # define CPPAD_HAS_GETTIMEOFDAY 1 /*! \def CPPAD_SIZE_T_NOT_UNSIGNED_INT If this symbol is zero, the type size_t is the same as the type unsigned int, otherwise this symbol is one. */ # define CPPAD_SIZE_T_NOT_UNSIGNED_INT 1 /*! \def CPPAD_TAPE_ADDR_TYPE Is the type used to store address on the tape. If not size_t, then sizeof(CPPAD_TAPE_ADDR_TYPE) <= sizeof( size_t ) to conserve memory. This type must support \c std::numeric_limits, the \c <= operator, and conversion to \c size_t. Make sure that the type chosen returns true for is_pod in pod_vector.hpp. This type is later defined as \c addr_t in the CppAD namespace. */ # define CPPAD_TAPE_ADDR_TYPE unsigned int /*! \def CPPAD_TAPE_ID_TYPE Is the type used to store tape identifiers. If not size_t, then sizeof(CPPAD_TAPE_ID_TYPE) <= sizeof( size_t ) to conserve memory. This type must support \c std::numeric_limits, the \c <= operator, and conversion to \c size_t. Make sure that the type chosen returns true for is_pod in pod_vector.hpp. This type is later defined as \c tape_id_t in the CppAD namespace. */ # define CPPAD_TAPE_ID_TYPE unsigned int /*! \def CPPAD_MAX_NUM_THREADS Specifies the maximum number of threads that CppAD can support (must be greater than or equal four). The user may define CPPAD_MAX_NUM_THREADS before including any of the CppAD header files. If it is not yet defined, */ # ifndef CPPAD_MAX_NUM_THREADS # define CPPAD_MAX_NUM_THREADS 48 # endif # endif TMB/inst/include/cppad/NearEqual.h0000644000176200001440000000005414113627761016420 0ustar liggesusers/* $Id$ */ # include "cppad/near_equal.hpp" TMB/inst/include/cppad/COPYING0000644000176200001440000002757514113627761015446 0ustar liggesusers/* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-06 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ GNU General Public License Version 3 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. TMB/inst/include/cppad/LuInvert.h0000644000176200001440000000005314113627761016312 0ustar liggesusers/* $Id$ */ # include "cppad/lu_invert.hpp" TMB/inst/include/cppad/CheckNumericType.h0000644000176200001440000000006414113627761017746 0ustar liggesusers/* $Id$ */ # include "cppad/check_numeric_type.hpp" TMB/inst/include/cppad/OdeErrControl.h0000644000176200001440000000006114113627761017262 0ustar liggesusers/* $Id$ */ # include "cppad/ode_err_control.hpp" TMB/inst/include/cppad/LuFactor.h0000644000176200001440000000005314113627761016261 0ustar liggesusers/* $Id$ */ # include "cppad/lu_factor.hpp" TMB/inst/include/cppad/runge_45.hpp0000644000176200001440000002664214536067013016543 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_RUNGE_45_INCLUDED # define CPPAD_RUNGE_45_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Runge45$$ $spell std fabs cppad.hpp bool xf templated const Runge-Kutta CppAD xi ti tf Karp $$ $index Runge45$$ $index ODE, Runge-Kutta$$ $index Runge, ODE$$ $index Kutta, ODE$$ $index solve, ODE$$ $index differential, equation$$ $index equation, differential$$ $section An Embedded 4th and 5th Order Runge-Kutta ODE Solver$$ $head Syntax$$ $codei%# include %$$ $icode%xf% = Runge45(%F%, %M%, %ti%, %tf%, %xi%) %$$ $icode%xf% = Runge45(%F%, %M%, %ti%, %tf%, %xi%, %e%) %$$ $head Purpose$$ This is an implementation of the Cash-Karp embedded 4th and 5th order Runge-Kutta ODE solver described in Section 16.2 of $cref/Numerical Recipes/Bib/Numerical Recipes/$$. We use $latex n$$ for the size of the vector $icode xi$$. Let $latex \B{R}$$ denote the real numbers and let $latex F : \B{R} \times \B{R}^n \rightarrow \B{R}^n$$ be a smooth function. The return value $icode xf$$ contains a 5th order approximation for the value $latex X(tf)$$ where $latex X : [ti , tf] \rightarrow \B{R}^n$$ is defined by the following initial value problem: $latex \[ \begin{array}{rcl} X(ti) & = & xi \\ X'(t) & = & F[t , X(t)] \end{array} \] $$ If your set of ordinary differential equations are stiff, an implicit method may be better (perhaps $cref Rosen34$$.) $head Operation Sequence$$ The $cref/operation sequence/glossary/Operation/Sequence/$$ for $icode Runge$$ does not depend on any of its $icode Scalar$$ input values provided that the operation sequence for $codei% %F%.Ode(%t%, %x%, %f%) %$$ does not on any of its $icode Scalar$$ inputs (see below). $head Include$$ The file $code cppad/runge_45.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head xf$$ The return value $icode xf$$ has the prototype $codei% %Vector% %xf% %$$ and the size of $icode xf$$ is equal to $icode n$$ (see description of $cref/Vector/Runge45/Vector/$$ below). $latex \[ X(tf) = xf + O( h^6 ) \] $$ where $latex h = (tf - ti) / M$$ is the step size. If $icode xf$$ contains not a number $cref nan$$, see the discussion for $cref/f/Runge45/Fun/f/$$. $head Fun$$ The class $icode Fun$$ and the object $icode F$$ satisfy the prototype $codei% %Fun% &%F% %$$ The object $icode F$$ (and the class $icode Fun$$) must have a member function named $code Ode$$ that supports the syntax $codei% %F%.Ode(%t%, %x%, %f%) %$$ $subhead t$$ The argument $icode t$$ to $icode%F%.Ode%$$ has prototype $codei% const %Scalar% &%t% %$$ (see description of $cref/Scalar/Runge45/Scalar/$$ below). $subhead x$$ The argument $icode x$$ to $icode%F%.Ode%$$ has prototype $codei% const %Vector% &%x% %$$ and has size $icode n$$ (see description of $cref/Vector/Runge45/Vector/$$ below). $subhead f$$ The argument $icode f$$ to $icode%F%.Ode%$$ has prototype $codei% %Vector% &%f% %$$ On input and output, $icode f$$ is a vector of size $icode n$$ and the input values of the elements of $icode f$$ do not matter. On output, $icode f$$ is set equal to $latex F(t, x)$$ in the differential equation. If any of the elements of $icode f$$ have the value not a number $code nan$$ the routine $code Runge45$$ returns with all the elements of $icode xf$$ and $icode e$$ equal to $code nan$$. $subhead Warning$$ The argument $icode f$$ to $icode%F%.Ode%$$ must have a call by reference in its prototype; i.e., do not forget the $code &$$ in the prototype for $icode f$$. $head M$$ The argument $icode M$$ has prototype $codei% size_t %M% %$$ It specifies the number of steps to use when solving the differential equation. This must be greater than or equal one. The step size is given by $latex h = (tf - ti) / M$$, thus the larger $icode M$$, the more accurate the return value $icode xf$$ is as an approximation for $latex X(tf)$$. $head ti$$ The argument $icode ti$$ has prototype $codei% const %Scalar% &%ti% %$$ (see description of $cref/Scalar/Runge45/Scalar/$$ below). It specifies the initial time for $icode t$$ in the differential equation; i.e., the time corresponding to the value $icode xi$$. $head tf$$ The argument $icode tf$$ has prototype $codei% const %Scalar% &%tf% %$$ It specifies the final time for $icode t$$ in the differential equation; i.e., the time corresponding to the value $icode xf$$. $head xi$$ The argument $icode xi$$ has the prototype $codei% const %Vector% &%xi% %$$ and the size of $icode xi$$ is equal to $icode n$$. It specifies the value of $latex X(ti)$$ $head e$$ The argument $icode e$$ is optional and has the prototype $codei% %Vector% &%e% %$$ If $icode e$$ is present, the size of $icode e$$ must be equal to $icode n$$. The input value of the elements of $icode e$$ does not matter. On output it contains an element by element estimated bound for the absolute value of the error in $icode xf$$ $latex \[ e = O( h^5 ) \] $$ where $latex h = (tf - ti) / M$$ is the step size. If on output, $icode e$$ contains not a number $code nan$$, see the discussion for $cref/f/Runge45/Fun/f/$$. $head Scalar$$ The type $icode Scalar$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. $subhead fabs$$ In addition, the following function must be defined for $icode Scalar$$ objects $icode a$$ and $icode b$$ $codei% %a% = fabs(%b%) %$$ Note that this operation is only used for computing $icode e$$; hence the operation sequence for $icode xf$$ can still be independent of the arguments to $code Runge45$$ even if $codei% fabs(%b%) = std::max(-%b%, %b%) %$$. $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type Scalar/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Parallel Mode$$ $index parallel, Runge45$$ $index Runge45, parallel$$ For each set of types $cref/Scalar/Runge45/Scalar/$$, $cref/Vector/Runge45/Vector/$$, and $cref/Fun/Runge45/Fun/$$, the first call to $code Runge45$$ must not be $cref/parallel/ta_in_parallel/$$ execution mode. $head Example$$ $children% example/runge45_1.cpp% example/runge45_2.cpp %$$ The file $cref runge45_1.cpp$$ contains a simple example and test of $code Runge45$$. It returns true if it succeeds and false otherwise. $pre $$ The file $cref runge45_2.cpp$$ contains an example using $code Runge45$$ in the context of algorithmic differentiation. It also returns true if it succeeds and false otherwise. $head Source Code$$ The source code for this routine is in the file $code cppad/runge_45.hpp$$. $end -------------------------------------------------------------------------- */ # include # include # include # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include namespace CppAD { // BEGIN CppAD namespace template Vector Runge45( Fun &F , size_t M , const Scalar &ti , const Scalar &tf , const Vector &xi ) { Vector e( xi.size() ); return Runge45(F, M, ti, tf, xi, e); } template Vector Runge45( Fun &F , size_t M , const Scalar &ti , const Scalar &tf , const Vector &xi , Vector &e ) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; // check numeric type specifications CheckNumericType(); // check simple vector class specifications CheckSimpleVector(); // Cash-Karp parameters for embedded Runge-Kutta method // are static to avoid recalculation on each call and // do not use Vector to avoid possible memory leak static Scalar a[6] = { Scalar(0), Scalar(1) / Scalar(5), Scalar(3) / Scalar(10), Scalar(3) / Scalar(5), Scalar(1), Scalar(7) / Scalar(8) }; static Scalar b[5 * 5] = { Scalar(1) / Scalar(5), Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(3) / Scalar(40), Scalar(9) / Scalar(40), Scalar(0), Scalar(0), Scalar(0), Scalar(3) / Scalar(10), -Scalar(9) / Scalar(10), Scalar(6) / Scalar(5), Scalar(0), Scalar(0), -Scalar(11) / Scalar(54), Scalar(5) / Scalar(2), -Scalar(70) / Scalar(27), Scalar(35) / Scalar(27), Scalar(0), Scalar(1631) / Scalar(55296), Scalar(175) / Scalar(512), Scalar(575) / Scalar(13824), Scalar(44275) / Scalar(110592), Scalar(253) / Scalar(4096) }; static Scalar c4[6] = { Scalar(2825) / Scalar(27648), Scalar(0), Scalar(18575) / Scalar(48384), Scalar(13525) / Scalar(55296), Scalar(277) / Scalar(14336), Scalar(1) / Scalar(4), }; static Scalar c5[6] = { Scalar(37) / Scalar(378), Scalar(0), Scalar(250) / Scalar(621), Scalar(125) / Scalar(594), Scalar(0), Scalar(512) / Scalar(1771) }; CPPAD_ASSERT_KNOWN( M >= 1, "Error in Runge45: the number of steps is less than one" ); CPPAD_ASSERT_KNOWN( e.size() == xi.size(), "Error in Runge45: size of e not equal to size of xi" ); size_t i, j, k, m; // indices size_t n = xi.size(); // number of components in X(t) Scalar ns = Scalar(int(M)); // number of steps as Scalar object Scalar h = (tf - ti) / ns; // step size Scalar zero_or_nan = Scalar(0); // zero (nan if Ode returns has a nan) for(i = 0; i < n; i++) // initialize e = 0 e[i] = zero_or_nan; // vectors used to store values returned by F Vector fh(6 * n), xtmp(n), ftmp(n), x4(n), x5(n), xf(n); xf = xi; // initialize solution for(m = 0; m < M; m++) { // time at beginning of this interval // (convert to int to avoid MS compiler warning) Scalar t = ti * (Scalar(int(M - m)) / ns) + tf * (Scalar(int(m)) / ns); // loop over integration steps x4 = x5 = xf; // start x4 and x5 at same point for each step for(j = 0; j < 6; j++) { // loop over function evaluations for this step xtmp = xf; // location for next function evaluation for(k = 0; k < j; k++) { // loop over previous function evaluations Scalar bjk = b[ (j-1) * 5 + k ]; for(i = 0; i < n; i++) { // loop over elements of x xtmp[i] += bjk * fh[i * 6 + k]; } } // ftmp = F(t + a[j] * h, xtmp) F.Ode(t + a[j] * h, xtmp, ftmp); // if ftmp has a nan, set zero_or_nan to nan for(i = 0; i < n; i++) zero_or_nan *= ftmp[i]; for(i = 0; i < n; i++) { // loop over elements of x Scalar fhi = ftmp[i] * h; fh[i * 6 + j] = fhi; x4[i] += c4[j] * fhi; x5[i] += c5[j] * fhi; x5[i] += zero_or_nan; } } // accumulate error bound for(i = 0; i < n; i++) { // cant use abs because cppad.hpp may not be included Scalar diff = x5[i] - x4[i]; e[i] += fabs(diff); e[i] += zero_or_nan; } // advance xf for this step using x5 xf = x5; } return xf; } } // End CppAD namespace # endif TMB/inst/include/cppad/base_require.hpp0000644000176200001440000000735614536067012017561 0ustar liggesusers// $Id$ # ifndef CPPAD_BASE_REQUIRE_INCLUDED # define CPPAD_BASE_REQUIRE_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin base_require$$ $spell ostream alloc eps std Lt Le Eq Ge Gt cppad.hpp namespace acos asin atan cos sqrt optimizations bool const CppAD enum Lt Le Eq Ge Gt inline Op std CondExp $$ $index Base, require$$ $index require, Base type$$ $index type, Base require$$ $section AD Requirements for Base Type$$ $head Syntax$$ $code include $$ $head Warning$$ This is a preliminary version of these specifications and it is subject to change in future versions of CppAD. $head Purpose$$ This section lists the requirements that the type $icode Base$$ so that the type $codei%AD<%Base%>%$$ can be used. $subhead Standard Base Types$$ In the case where $icode Base$$ is $code float$$, $code double$$, $code std::complex$$, $code std::complex$$, or $codei%AD<%Other%>%$$, these requirements are provided by including the file $code cppad/cppad.hpp$$. $head Include Order$$ If you are linking a non-standard base type to CppAD, you must first include the file $code cppad/base_require.hpp$$, then provide the specifications below, and then include the file $code cppad/cppad.hpp$$. $head Numeric Type$$ The type $icode Base$$ must support all the operations for a $cref NumericType$$. $head Output Operator$$ $index output, base operator$$ $index base, output operator$$ $index operator, base output$$ The type $icode Base$$ must support the syntax $codei% %os% << %x% %$$ where $icode os$$ is an $code std::ostream&$$ and $icode x$$ is a $code const base_alloc&$$. For example, see $cref/base_alloc/base_alloc.hpp/Output Operator/$$. $head Integer$$ $index Integer, base require$$ $index base, Integer require$$ $index require, base Integer$$ The type $icode Base$$ must support the syntax $codei% %i% = CppAD::Integer(%x%) %$$ which converts $icode x$$ to an $code int$$. The argument $icode x$$ has prototype $codei% const %Base%& %x% %$$ and the return value $icode i$$ has prototype $codei% int %i% %$$ $subhead Suggestion$$ In many cases, the $icode Base$$ version of the $code Integer$$ function can be defined by $codei% namespace CppAD { inline int Integer(const %Base%& x) { return static_cast(x); } } %$$ For example, see $cref/base_float/base_float.hpp/Integer/$$ and $cref/base_alloc/base_alloc.hpp/Integer/$$. $childtable% omh/base_require/base_member.omh% cppad/local/base_cond_exp.hpp% omh/base_require/base_identical.omh% omh/base_require/base_ordered.omh% cppad/local/base_std_math.hpp% omh/base_require/base_example.omh %$$ $end */ // definitions that must come before base implementations # include # include # include # include // grouping documentation by feature # include # include // must define template class numeric_limits before the base cases # include # include // deprecated // base cases that come with CppAD # include # include # include # endif TMB/inst/include/cppad/speed_test.hpp0000644000176200001440000002567214536067013017254 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_SPEED_TEST_INCLUDED # define CPPAD_SPEED_TEST_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin speed_test$$ $spell gettimeofday vec cppad.hpp Microsoft namespace std const Rcout ctime ifdef const endif cpp $$ $index speed_test$$ $index test, speed$$ $section Run One Speed Test and Return Results$$ $head Syntax$$ $code # include $$ $pre $$ $icode%rate_vec% = speed_test(%test%, %size_vec%, %time_min%)%$$ $head Purpose$$ The $code speed_test$$ function executes a speed test for various sized problems and reports the rate of execution. $head Motivation$$ It is important to separate small calculation units and test them individually. This way individual changes can be tested in the context of the routine that they are in. On many machines, accurate timing of a very short execution sequences is not possible. In addition, there may be set up and tear down time for a test that we do not really want included in the timing. For this reason $code speed_test$$ automatically determines how many times to repeat the section of the test that we wish to time. $head Include$$ The file $code cppad/speed_test.hpp$$ defines the $code speed_test$$ function. This file is included by $code cppad/cppad.hpp$$ and it can also be included separately with out the rest of the $code CppAD$$ routines. $head Vector$$ We use $icode Vector$$ to denote a $cref/simple vector class/SimpleVector/$$ with elements of type $code size_t$$. $head test$$ The $code speed_test$$ argument $icode test$$ is a function with the syntax $codei% %test%(%size%, %repeat%) %$$ and its return value is $code void$$. $subhead size$$ The $icode test$$ argument $icode size$$ has prototype $codei% size_t %size% %$$ It specifies the size for this test. $subhead repeat$$ The $icode test$$ argument $icode repeat$$ has prototype $codei% size_t %repeat% %$$ It specifies the number of times to repeat the test. $head size_vec$$ The $code speed_test$$ argument $icode size_vec$$ has prototype $codei% const %Vector%& %size_vec% %$$ This vector determines the size for each of the tests problems. $head time_min$$ The argument $icode time_min$$ has prototype $codei% double %time_min% %$$ It specifies the minimum amount of time in seconds that the $icode test$$ routine should take. The $icode repeat$$ argument to $icode test$$ is increased until this amount of execution time is reached. $head rate_vec$$ The return value $icode rate_vec$$ has prototype $codei% %Vector%& %rate_vec% %$$ We use $latex n$$ to denote its size which is the same as the vector $icode size_vec$$. For $latex i = 0 , \ldots , n-1$$, $codei% %rate_vec%[%i%] %$$ is the ratio of $icode repeat$$ divided by time in seconds for the problem with size $icode%size_vec%[%i%]%$$. $head Timing$$ If your system supports the unix $code gettimeofday$$ function, it will be used to measure time. Otherwise, time is measured by the difference in $codep (double) clock() / (double) CLOCKS_PER_SEC $$ in the context of the standard $code $$ definitions. $children% speed/example/speed_test.cpp %$$ $head Example$$ The routine $cref speed_test.cpp$$ is an example and test of $code speed_test$$. $end ----------------------------------------------------------------------- */ # include # include # include # include namespace CppAD { // BEGIN CppAD namespace // implemented as an inline so that can include in multiple link modules // with this same file template inline Vector speed_test( void test(size_t size, size_t repeat), const Vector& size_vec , double time_min ) { // check that size_vec is a simple vector with size_t elements CheckSimpleVector(); size_t n = size_vec.size(); Vector rate_vec(n); size_t i; for(i = 0; i < n; i++) { size_t size = size_vec[i]; size_t repeat = 1; double s0 = elapsed_seconds(); double s1 = elapsed_seconds(); while( s1 - s0 < time_min ) { repeat = 2 * repeat; s0 = elapsed_seconds(); test(size, repeat); s1 = elapsed_seconds(); } rate_vec[i] = (size_t)(.5 + repeat / (s1 - s0)); } return rate_vec; } } // END CppAD namespace /* $begin SpeedTest$$ $spell cppad.hpp Microsoft namespace std const Rcout ctime ifdef const endif cpp $$ $index SpeedTest$$ $index test, speed$$ $section Run One Speed Test and Print Results$$ $head Syntax$$ $code # include $$ $pre $$ $codei%SpeedTest(%Test%, %first%, %inc%, %last%)%$$ $head Purpose$$ The $code SpeedTest$$ function executes a speed test for various sized problems and reports the results on standard output; i.e. $code Rcout$$. The size of each test problem is included in its report (unless $icode first$$ is equal to $icode last$$). $head Motivation$$ It is important to separate small calculation units and test them individually. This way individual changes can be tested in the context of the routine that they are in. On many machines, accurate timing of a very short execution sequences is not possible. In addition, there may be set up time for a test that we do not really want included in the timing. For this reason $code SpeedTest$$ automatically determines how many times to repeat the section of the test that we wish to time. $head Include$$ The file $code speed_test.hpp$$ contains the $code SpeedTest$$ function. This file is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Test$$ The $code SpeedTest$$ argument $icode Test$$ is a function with the syntax $codei% %name% = %Test%(%size%, %repeat%) %$$ $subhead size$$ The $icode Test$$ argument $icode size$$ has prototype $codei% size_t %size% %$$ It specifies the size for this test. $subhead repeat$$ The $icode Test$$ argument $icode repeat$$ has prototype $codei% size_t %repeat% %$$ It specifies the number of times to repeat the test. $subhead name$$ The $icode Test$$ result $icode name$$ has prototype $codei% std::string %name% %$$ The results for this test are reported on $code Rcout$$ with $icode name$$ as an identifier for the test. It is assumed that, for the duration of this call to $code SpeedTest$$, $icode Test$$ will always return the same value for $icode name$$. If $icode name$$ is the empty string, no test name is reported by $code SpeedTest$$. $head first$$ The $code SpeedTest$$ argument $icode first$$ has prototype $codei% size_t %first% %$$ It specifies the size of the first test problem reported by this call to $code SpeedTest$$. $head last$$ The $code SpeedTest$$ argument $icode last$$ has prototype $codei% size_t %last% %$$ It specifies the size of the last test problem reported by this call to $code SpeedTest$$. $head inc$$ The $code SpeedTest$$ argument $icode inc$$ has prototype $codei% int %inc% %$$ It specifies the increment between problem sizes; i.e., all values of $icode size$$ in calls to $icode Test$$ are given by $codei% %size% = %first% + %j% * %inc% %$$ where $icode j$$ is a positive integer. The increment can be positive or negative but it cannot be zero. The values $icode first$$, $icode last$$ and $icode inc$$ must satisfy the relation $latex \[ inc * ( last - first ) \geq 0 \] $$ $head rate$$ The value displayed in the $code rate$$ column on $code Rcout$$ is defined as the value of $icode repeat$$ divided by the corresponding elapsed execution time in seconds. The elapsed execution time is measured by the difference in $codep (double) clock() / (double) CLOCKS_PER_SEC $$ in the context of the standard $code $$ definitions. $head Errors$$ If one of the restrictions above is violated, the CppAD error handler is used to report the error. You can redefine this action using the instructions in $cref ErrorHandler$$ $head Example$$ $children% speed/example/speed_program.cpp %$$ The program $cref speed_program.cpp$$ is an example usage of $code SpeedTest$$. $end ----------------------------------------------------------------------- */ // BEGIN C++ # include # include # include # include namespace CppAD { // BEGIN CppAD namespace inline void SpeedTestNdigit(size_t value, size_t &ndigit, size_t &pow10) { pow10 = 10; ndigit = 1; while( pow10 <= value ) { pow10 *= 10; ndigit += 1; } } // implemented as an inline so that can include in multiple link modules // with this same file inline void SpeedTest( std::string Test(size_t size, size_t repeat), size_t first, int inc, size_t last ) { using std::endl; size_t size; size_t repeat; size_t rate; size_t digit; size_t ndigit; size_t pow10; size_t maxSize; size_t maxSizeDigit; double s0; double s1; std::string name; CPPAD_ASSERT_KNOWN( inc != 0 && first != 0 && last != 0, "inc, first, or last is zero in call to SpeedTest" ); CPPAD_ASSERT_KNOWN( (inc > 0 && first <= last) || (inc < 0 && first >= last), "SpeedTest: increment is positive and first > last or " "increment is negative and first < last" ); // compute maxSize maxSize = size = first; while( (inc > 0 && size <= last) || (inc < 0 && size >= last) ) { if( size > maxSize ) maxSize = size; // next size if( ((int) size) + inc > 0 ) size += inc; else size = 0; } SpeedTestNdigit(maxSize, maxSizeDigit, pow10); size = first; while( (inc > 0 && size <= last) || (inc < 0 && size >= last) ) { repeat = 1; s0 = elapsed_seconds(); s1 = elapsed_seconds(); while( s1 - s0 < 1. ) { repeat = 2 * repeat; s0 = elapsed_seconds(); name = Test(size, repeat); s1 = elapsed_seconds(); } rate = (size_t)(.5 + repeat / (s1 - s0)); if( size == first && name != "" ) Rcout << name << endl; if( first != last ) { // convert int(size_t) to avoid warning on _MSC_VER sys Rcout << "size = " << int(size); SpeedTestNdigit(size, ndigit, pow10); while( ndigit < maxSizeDigit ) { Rcout << " "; ndigit++; } Rcout << " "; } Rcout << "rate = "; SpeedTestNdigit(rate, ndigit, pow10); while( ndigit > 0 ) { pow10 /= 10; digit = rate / pow10; // convert int(size_t) to avoid warning on _MSC_VER sys Rcout << int(digit); rate = rate % pow10; ndigit -= 1; if( (ndigit > 0) && (ndigit % 3 == 0) ) Rcout << ","; } Rcout << endl; // next size if( ((int) size) + inc > 0 ) size += inc; else size = 0; } return; } } // END CppAD namespace // END C++ # endif TMB/inst/include/cppad/cppad.hpp0000644000176200001440000000650614536067012016176 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_CPPAD_INCLUDED # define CPPAD_CPPAD_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /*! \file cppad.hpp \brief includes the entire CppAD package in the necessary order. \namespace CppAD \brief contains all the variables and functions defined by the CppAD package. */ # include // all base type requirements // --------------------------------------------------------------------------- // CppAD general purpose library routines (can be included separately) # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include // -------------------------------------------------------------------------- // System routines that can be used by rest of CppAD with out including # include # include # include # include // --------------------------------------------------------------------------- // definitions needed by rest of includes // definitions that come from the installation # include // definitions that are local to the CppAD include files # include // vectors used with CppAD # include // deprecated vectors used with CppAD # include // Declare classes and fucntions that are used before defined # include // --------------------------------------------------------------------------- // declare the AD template class # include // --------------------------------------------------------------------------- # include // AD class methods available to the user // tape that tape for AD acts as a user of Base operations // so user_ad.hpp must come before op.hpp # include // executes taped operations # include // ADFun objects // --------------------------------------------------------------------------- // library routines that require the rest of CppAD # include # include # include // undo definitions in Define.h # include # endif TMB/inst/include/cppad/time_test.hpp0000644000176200001440000001366014536067013017104 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_TIME_TEST_INCLUDED # define CPPAD_TIME_TEST_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin time_test$$ $spell gettimeofday vec cppad.hpp Microsoft namespace std const Rcout ctime ifdef const endif cpp $$ $index time_test$$ $index test, speed$$ $index test, time$$ $section Determine Amount of Time to Execute a Test$$ $head Syntax$$ $codei%# include %$$ $icode%time% = time_test(%test%, %time_min%)%$$ $icode%time% = time_test(%test%, %time_min%, %test_size%)%$$ $head Purpose$$ The $code time_test$$ function executes a timing test and reports the amount of wall clock time for execution. $head Motivation$$ It is important to separate small calculation units and test them individually. This way individual changes can be tested in the context of the routine that they are in. On many machines, accurate timing of a very short execution sequences is not possible. In addition, there may be set up and tear down time for a test that we do not really want included in the timing. For this reason $code time_test$$ automatically determines how many times to repeat the section of the test that we wish to time. $head Include$$ The file $code cppad/time_test.hpp$$ defines the $code time_test$$ function. This file is included by $code cppad/cppad.hpp$$ and it can also be included separately with out the rest of the $code CppAD$$ routines. $head test$$ The $code time_test$$ argument $icode test$$ is a function, or function object. In the case where $icode test_size$$ is not present, $icode test$$ supports the syntax $codei% %test%(%repeat%) %$$ In the case where $icode test_size$$ is present, $icode test$$ supports the syntax $codei% %test%(%size%, %repeat%) %$$ In either case, the return value for $icode test$$ is $code void$$. $subhead size$$ If the argument $icode size$$ is present, it has prototype $codei% size_t %size% %$$ and is equal to the $icode test_size$$ argument to $code time_test$$. $subhead repeat$$ The $icode test$$ argument $icode repeat$$ has prototype $codei% size_t %repeat% %$$ It will be equal to the $icode size$$ argument to $code time_test$$. $head time_min$$ The argument $icode time_min$$ has prototype $codei% double %time_min% %$$ It specifies the minimum amount of time in seconds that the $icode test$$ routine should take. The $icode repeat$$ argument to $icode test$$ is increased until this amount of execution time (or more) is reached. $head test_size$$ This argument has prototype $codei% size_t %test_size% %$$ It specifies the $icode size$$ argument to $icode test$$. $head time$$ The return value $icode time$$ has prototype $codei% double %time% %$$ and is the number of wall clock seconds that it took to execute $icode test$$ divided by the value used for $icode repeat$$. $head Timing$$ The routine $cref elapsed_seconds$$ will be used to determine the amount of time it took to execute the test. $children% cppad/elapsed_seconds.hpp% speed/example/time_test.cpp %$$ $head Example$$ The routine $cref time_test.cpp$$ is an example and test of $code time_test$$. $end ----------------------------------------------------------------------- */ # include # include # include # include # define CPPAD_EXTRA_RUN_BEFORE_TIMING 0 namespace CppAD { // BEGIN_CPPAD_NAMESPACE /*! \file time_test.hpp \brief Function that preforms one timing test (for speed of execution). */ /*! Preform one wall clock execution timing test. \tparam Test Either the type void (*)(size_t) or a function object type that supports the same syntax. \param test The function, or function object, that supports the operation test(repeat) where \c repeat is the number of times to repeat the tests operaiton that is being timed. \param time_min is the minimum amount of time that \c test should take to preform the repetitions of the operation being timed. */ template double time_test(Test test, double time_min ) { # if CPPAD_EXTRA_RUN_BEFORE_TIMING test(1); # endif size_t repeat = 0; double s0 = elapsed_seconds(); double s1 = s0; while( s1 - s0 < time_min ) { repeat = std::max(size_t(1), 2 * repeat); s0 = elapsed_seconds(); test(repeat); s1 = elapsed_seconds(); } double time = (s1 - s0) / double(repeat); return time; } /*! Preform one wall clock execution timing test. \tparam Test Either the type void (*)(size_t, size_t) or a function object type that supports the same syntax. \param test The function, or function object, that supports the operation test(size, repeat) where \c is the size for this test and \c repeat is the number of times to repeat the tests operaiton that is being timed. \param time_min is the minimum amount of time that \c test should take to preform the repetitions of the operation being timed. \param test_size will be used for the value of \c size in the call to \c test. */ template double time_test(Test test, double time_min, size_t test_size) { # if CPPAD_EXTRA_RUN_BEFORE_TIMING test(test_size, 1); # endif size_t repeat = 0; double s0 = elapsed_seconds(); double s1 = s0; while( s1 - s0 < time_min ) { repeat = std::max(size_t(1), 2 * repeat); s0 = elapsed_seconds(); test(test_size, repeat); s1 = elapsed_seconds(); } double time = (s1 - s0) / double(repeat); return time; } } // END_CPPAD_NAMESPACE # undef CPPAD_EXTRA_RUN_BEFORE_TIMING // END PROGRAM # endif TMB/inst/include/cppad/near_equal.hpp0000644000176200001440000001400214536067012017211 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_NEAR_EQUAL_INCLUDED # define CPPAD_NEAR_EQUAL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin NearEqual$$ $spell cppad.hpp sqrt Rcout endl Microsoft std Cpp namespace const bool $$ $section Determine if Two Values Are Nearly Equal$$ $index NearEqual$$ $index equal, near$$ $index absolute, difference$$ $index relative, difference$$ $index difference, absolute$$ $index difference, relative$$ $head Syntax$$ $code # include $$ $pre $$ $icode%b% = NearEqual(%x%, %y%, %r%, %a%)%$$ $head Purpose$$ Returns true, if $icode x$$ and $icode y$$ are nearly equal, and false otherwise. $head x$$ The argument $icode x$$ has one of the following possible prototypes $codei% const %Type% &%x%, const std::complex<%Type%> &%x%, %$$ $head y$$ The argument $icode y$$ has one of the following possible prototypes $codei% const %Type% &%y%, const std::complex<%Type%> &%y%, %$$ $head r$$ The relative error criteria $icode r$$ has prototype $codei% const %Type% &%r% %$$ It must be greater than or equal to zero. The relative error condition is defined as: $latex \[ | x - y | \leq r ( |x| + |y| ) \] $$ $head a$$ The absolute error criteria $icode a$$ has prototype $codei% const %Type% &%a% %$$ It must be greater than or equal to zero. The absolute error condition is defined as: $latex \[ | x - y | \leq a \] $$ $head b$$ The return value $icode b$$ has prototype $codei% bool %b% %$$ If either $icode x$$ or $icode y$$ is infinite or not a number, the return value is false. Otherwise, if either the relative or absolute error condition (defined above) is satisfied, the return value is true. Otherwise, the return value is false. $head Type$$ The type $icode Type$$ must be a $cref NumericType$$. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, the following operations must be defined objects $icode a$$ and $icode b$$ of type $icode Type$$: $table $bold Operation$$ $cnext $bold Description$$ $rnext $icode%a% <= %b%$$ $cnext less that or equal operator (returns a $code bool$$ object) $tend $head Include Files$$ The file $code cppad/near_equal.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Example$$ $children% example/near_equal.cpp %$$ The file $cref near_equal.cpp$$ contains an example and test of $code NearEqual$$. It return true if it succeeds and false otherwise. $head Exercise$$ $index exercise, NearEqual$$ Create and run a program that contains the following code: $codep using std::complex; using std::endl; complex one(1., 0), i(0., 1); complex x = one / i; complex y = - i; double r = 1e-12; double a = 0; bool ok = CppAD::NearEqual(x, y, r, a); if( ok ) Rcout << "Ok" << endl; else Rcout << "Error" << endl; $$ $end */ # include # include # include namespace CppAD { // Begin CppAD namespace // determine if both x and y are finite values (z1 and z2 are zero). template bool near_equal_isfinite( const Type &z1, const Type &z2, const Type &x , const Type &y) { Type infinity = Type(1) / z1; Type nan = z1 / z2; // handle bug where some compilers return true for nan == nan bool xNan = ( x != x || x == nan ); bool yNan = ( y != y || y == nan ); // infinite cases bool xInf = (x == infinity || x == - infinity); bool yInf = (x == infinity || x == - infinity); return ! (xNan | yNan | xInf | yInf); } template bool NearEqual(const Type &x, const Type &y, const Type &r, const Type &a) { CheckNumericType(); Type zero(0); CPPAD_ASSERT_KNOWN( zero <= r, "Error in NearEqual: relative error is less than zero" ); CPPAD_ASSERT_KNOWN( zero <= a, "Error in NearEqual: absolute error is less than zero" ); // check for special cases if( ! CppAD::near_equal_isfinite(zero, zero, x, y) ) return false; Type ax = x; if( ax <= zero ) ax = - ax; Type ay = y; if( ay <= zero ) ay = - ay; Type ad = x - y; if( ad <= zero ) ad = - ad; if( ad <= a ) return true; if( ad <= r * (ax + ay) ) return true; return false; } template bool NearEqual( const std::complex &x , const std::complex &y , const Type &r , const Type & a ) { CheckNumericType(); Type zero(0); CPPAD_ASSERT_KNOWN( zero <= r, "Error in NearEqual: relative error is less than zero" ); CPPAD_ASSERT_KNOWN( zero <= a, "Error in NearEqual: absolute error is less than zero" ); // check for special cases if( ! CppAD::near_equal_isfinite(zero, zero, x.real(), x.imag()) ) return false; if( ! CppAD::near_equal_isfinite(zero, zero, y.real(), y.imag()) ) return false; std::complex d = x - y; Type ad = std::abs(d); if( ad <= a ) return true; Type ax = std::abs(x); Type ay = std::abs(y); if( ad <= r * (ax + ay) ) return true; return false; } template bool NearEqual( const std::complex &x , const Type &y , const Type &r , const Type & a ) { return NearEqual(x, std::complex(y, Type(0)), r, a); } template bool NearEqual( const Type &x , const std::complex &y , const Type &r , const Type & a ) { return NearEqual(std::complex(x, Type(0)), y, r, a); } } // END CppAD namespace # endif TMB/inst/include/cppad/pow_int.hpp0000644000176200001440000000631114536067013016561 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_POW_INT_INCLUDED # define CPPAD_POW_INT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- $begin pow_int$$ $spell cppad.hpp CppAD namespace const $$ $index pow, integer$$ $index exponent, integer$$ $index integer, pow$$ $section The Integer Power Function$$ $head Syntax$$ $code # include $$ $pre $$ $icode%z% = pow(%x%, %y%)%$$ $head See Also$$ $cref pow$$ $head Purpose$$ Determines the value of the power function $latex \[ {\rm pow} (x, y) = x^y \] $$ for integer exponents $icode n$$ using multiplication and possibly division to compute the value. The other CppAD $cref pow$$ function may use logarithms and exponentiation to compute derivatives of the same value (which will not work if $icode x$$ is less than or equal zero). $head Include$$ The file $code cppad/pow_int.h$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. Including this file defines this version of the $code pow$$ within the $code CppAD$$ namespace. $head x$$ The argument $icode x$$ has prototype $codei% const %Type%& %x% %$$ $head y$$ The argument $icode y$$ has prototype $codei% const int& %y% %$$ $head z$$ The result $icode z$$ has prototype $codei% %Type% %z% %$$ $head Type$$ The type $icode Type$$ must support the following operations where $icode a$$ and $icode b$$ are $icode Type$$ objects and $icode i$$ is an $code int$$: $table $bold Operation$$ $pre $$ $cnext $bold Description$$ $cnext $bold Result Type$$ $rnext $icode%Type% %a%(%i%)%$$ $cnext construction of a $icode Type$$ object from an $code int$$ $cnext $icode Type$$ $rnext $icode%a% * %b%$$ $cnext binary multiplication of $icode Type$$ objects $cnext $icode Type$$ $rnext $icode%a% / %b%$$ $cnext binary division of $icode Type$$ objects $cnext $icode Type$$ $tend $head Operation Sequence$$ The $icode Type$$ operation sequence used to calculate $icode z$$ is $cref/independent/glossary/Operation/Independent/$$ of $icode x$$. $head Example$$ $children% example/pow_int.cpp %$$ The file $cref pow_int.cpp$$ is an example and test of this function. It returns true if it succeeds and false otherwise. $end ------------------------------------------------------------------------------- */ namespace CppAD { template inline Type pow (const Type& x, const int& n) { Type p(1); int n2 = n / 2; if( n == 0 ) return p; if( n < 0 ) return p / pow(x, -n); if( n == 1 ) return x; // p = (x^2)^(n/2) p = pow( x * x , n2 ); // n is even case if( n % 2 == 0 ) return p; // n is odd case return p * x; } } # endif TMB/inst/include/cppad/ode_gear_control.hpp0000644000176200001440000003341214536067012020410 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ODE_GEAR_CONTROL_INCLUDED # define CPPAD_ODE_GEAR_CONTROL_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin OdeGearControl$$ $spell cppad.hpp CppAD xf xi smin smax eabs ef maxabs nstep tf sini erel dep const tb ta exp $$ $index OdeGearControl$$ $index control, Ode Gear$$ $index error, Gear Ode$$ $index differential, Ode Gear control$$ $index equation, Ode Gear control$$ $section An Error Controller for Gear's Ode Solvers$$ $head Syntax$$ $codei%# include %$$ $icode%xf% = OdeGearControl(%F%, %M%, %ti%, %tf%, %xi%, %smin%, %smax%, %sini%, %eabs%, %erel%, %ef% , %maxabs%, %nstep% )%$$ $head Purpose$$ Let $latex \B{R}$$ denote the real numbers and let $latex f : \B{R} \times \B{R}^n \rightarrow \B{R}^n$$ be a smooth function. We define $latex X : [ti , tf] \rightarrow \B{R}^n$$ by the following initial value problem: $latex \[ \begin{array}{rcl} X(ti) & = & xi \\ X'(t) & = & f[t , X(t)] \end{array} \] $$ The routine $cref OdeGear$$ is a stiff multi-step method that can be used to approximate the solution to this equation. The routine $code OdeGearControl$$ sets up this multi-step method and controls the error during such an approximation. $head Include$$ The file $code cppad/ode_gear_control.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Notation$$ The template parameter types $cref/Scalar/OdeGearControl/Scalar/$$ and $cref/Vector/OdeGearControl/Vector/$$ are documented below. $head xf$$ The return value $icode xf$$ has the prototype $codei% %Vector% %xf% %$$ and the size of $icode xf$$ is equal to $icode n$$ (see description of $cref/Vector/OdeGear/Vector/$$ below). It is the approximation for $latex X(tf)$$. $head Fun$$ The class $icode Fun$$ and the object $icode F$$ satisfy the prototype $codei% %Fun% &%F% %$$ This must support the following set of calls $codei% %F%.Ode(%t%, %x%, %f%) %F%.Ode_dep(%t%, %x%, %f_x%) %$$ $subhead t$$ The argument $icode t$$ has prototype $codei% const %Scalar% &%t% %$$ (see description of $cref/Scalar/OdeGear/Scalar/$$ below). $subhead x$$ The argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ and has size $icode N$$ (see description of $cref/Vector/OdeGear/Vector/$$ below). $subhead f$$ The argument $icode f$$ to $icode%F%.Ode%$$ has prototype $codei% %Vector% &%f% %$$ On input and output, $icode f$$ is a vector of size $icode N$$ and the input values of the elements of $icode f$$ do not matter. On output, $icode f$$ is set equal to $latex f(t, x)$$ (see $icode f(t, x)$$ in $cref/Purpose/OdeGear/Purpose/$$). $subhead f_x$$ The argument $icode f_x$$ has prototype $codei% %Vector% &%f_x% %$$ On input and output, $icode f_x$$ is a vector of size $latex N * N$$ and the input values of the elements of $icode f_x$$ do not matter. On output, $latex \[ f\_x [i * n + j] = \partial_{x(j)} f_i ( t , x ) \] $$ $subhead Warning$$ The arguments $icode f$$, and $icode f_x$$ must have a call by reference in their prototypes; i.e., do not forget the $code &$$ in the prototype for $icode f$$ and $icode f_x$$. $head M$$ The argument $icode M$$ has prototype $codei% size_t %M% %$$ It specifies the order of the multi-step method; i.e., the order of the approximating polynomial (after the initialization process). The argument $icode M$$ must greater than or equal one. $head ti$$ The argument $icode ti$$ has prototype $codei% const %Scalar% &%ti% %$$ It specifies the initial time for the integration of the differential equation. $head tf$$ The argument $icode tf$$ has prototype $codei% const %Scalar% &%tf% %$$ It specifies the final time for the integration of the differential equation. $head xi$$ The argument $icode xi$$ has prototype $codei% const %Vector% &%xi% %$$ and size $icode n$$. It specifies value of $latex X(ti)$$. $head smin$$ The argument $icode smin$$ has prototype $codei% const %Scalar% &%smin% %$$ The minimum value of $latex T[M] - T[M-1]$$ in a call to $code OdeGear$$ will be $latex smin$$ except for the last two calls where it may be as small as $latex smin / 2$$. The value of $icode smin$$ must be less than or equal $icode smax$$. $head smax$$ The argument $icode smax$$ has prototype $codei% const %Scalar% &%smax% %$$ It specifies the maximum step size to use during the integration; i.e., the maximum value for $latex T[M] - T[M-1]$$ in a call to $code OdeGear$$. $head sini$$ The argument $icode sini$$ has prototype $codei% %Scalar% &%sini% %$$ The value of $icode sini$$ is the minimum step size to use during initialization of the multi-step method; i.e., for calls to $code OdeGear$$ where $latex m < M$$. The value of $icode sini$$ must be less than or equal $icode smax$$ (and can also be less than $icode smin$$). $head eabs$$ The argument $icode eabs$$ has prototype $codei% const %Vector% &%eabs% %$$ and size $icode n$$. Each of the elements of $icode eabs$$ must be greater than or equal zero. It specifies a bound for the absolute error in the return value $icode xf$$ as an approximation for $latex X(tf)$$. (see the $cref/error criteria discussion/OdeGearControl/Error Criteria Discussion/$$ below). $head erel$$ The argument $icode erel$$ has prototype $codei% const %Scalar% &%erel% %$$ and is greater than or equal zero. It specifies a bound for the relative error in the return value $icode xf$$ as an approximation for $latex X(tf)$$ (see the $cref/error criteria discussion/OdeGearControl/Error Criteria Discussion/$$ below). $head ef$$ The argument value $icode ef$$ has prototype $codei% %Vector% &%ef% %$$ and size $icode n$$. The input value of its elements does not matter. On output, it contains an estimated bound for the absolute error in the approximation $icode xf$$; i.e., $latex \[ ef_i > | X( tf )_i - xf_i | \] $$ $head maxabs$$ The argument $icode maxabs$$ is optional in the call to $code OdeGearControl$$. If it is present, it has the prototype $codei% %Vector% &%maxabs% %$$ and size $icode n$$. The input value of its elements does not matter. On output, it contains an estimate for the maximum absolute value of $latex X(t)$$; i.e., $latex \[ maxabs[i] \approx \max \left\{ | X( t )_i | \; : \; t \in [ti, tf] \right\} \] $$ $head nstep$$ The argument $icode nstep$$ has the prototype $codei% %size_t% &%nstep% %$$ Its input value does not matter and its output value is the number of calls to $cref OdeGear$$ used by $code OdeGearControl$$. $head Error Criteria Discussion$$ The relative error criteria $icode erel$$ and absolute error criteria $icode eabs$$ are enforced during each step of the integration of the ordinary differential equations. In addition, they are inversely scaled by the step size so that the total error bound is less than the sum of the error bounds. To be specific, if $latex \tilde{X} (t)$$ is the approximate solution at time $latex t$$, $icode ta$$ is the initial step time, and $icode tb$$ is the final step time, $latex \[ \left| \tilde{X} (tb)_j - X (tb)_j \right| \leq \frac{tf - ti}{tb - ta} \left[ eabs[j] + erel \; | \tilde{X} (tb)_j | \right] \] $$ If $latex X(tb)_j$$ is near zero for some $latex tb \in [ti , tf]$$, and one uses an absolute error criteria $latex eabs[j]$$ of zero, the error criteria above will force $code OdeGearControl$$ to use step sizes equal to $cref/smin/OdeGearControl/smin/$$ for steps ending near $latex tb$$. In this case, the error relative to $icode maxabs$$ can be judged after $code OdeGearControl$$ returns. If $icode ef$$ is to large relative to $icode maxabs$$, $code OdeGearControl$$ can be called again with a smaller value of $icode smin$$. $head Scalar$$ The type $icode Scalar$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, the following operations must be defined for $icode Scalar$$ objects $icode a$$ and $icode b$$: $table $bold Operation$$ $cnext $bold Description$$ $rnext $icode%a% <= %b%$$ $cnext returns true (false) if $icode a$$ is less than or equal (greater than) $icode b$$. $rnext $icode%a% == %b%$$ $cnext returns true (false) if $icode a$$ is equal to $icode b$$. $rnext $codei%log(%a%)%$$ $cnext returns a $icode Scalar$$ equal to the logarithm of $icode a$$ $rnext $codei%exp(%a%)%$$ $cnext returns a $icode Scalar$$ equal to the exponential of $icode a$$ $tend $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type Scalar/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Example$$ $children% example/ode_gear_control.cpp %$$ The file $cref ode_gear_control.cpp$$ contains an example and test a test of using this routine. It returns true if it succeeds and false otherwise. $head Theory$$ Let $latex e(s)$$ be the error as a function of the step size $latex s$$ and suppose that there is a constant $latex K$$ such that $latex e(s) = K s^m$$. Let $latex a$$ be our error bound. Given the value of $latex e(s)$$, a step of size $latex \lambda s$$ would be ok provided that $latex \[ \begin{array}{rcl} a & \geq & e( \lambda s ) (tf - ti) / ( \lambda s ) \\ a & \geq & K \lambda^m s^m (tf - ti) / ( \lambda s ) \\ a & \geq & \lambda^{m-1} s^{m-1} (tf - ti) e(s) / s^m \\ a & \geq & \lambda^{m-1} (tf - ti) e(s) / s \\ \lambda^{m-1} & \leq & \frac{a}{e(s)} \frac{s}{tf - ti} \end{array} \] $$ Thus if the right hand side of the last inequality is greater than or equal to one, the step of size $latex s$$ is ok. $head Source Code$$ The source code for this routine is in the file $code cppad/ode_gear_control.hpp$$. $end -------------------------------------------------------------------------- */ // link exp and log for float and double # include # include namespace CppAD { // Begin CppAD namespace template Vector OdeGearControl( Fun &F , size_t M , const Scalar &ti , const Scalar &tf , const Vector &xi , const Scalar &smin , const Scalar &smax , Scalar &sini , const Vector &eabs , const Scalar &erel , Vector &ef , Vector &maxabs, size_t &nstep ) { // check simple vector class specifications CheckSimpleVector(); // dimension of the state space size_t n = size_t(xi.size()); CPPAD_ASSERT_KNOWN( M >= 1, "Error in OdeGearControl: M is less than one" ); CPPAD_ASSERT_KNOWN( smin <= smax, "Error in OdeGearControl: smin is greater than smax" ); CPPAD_ASSERT_KNOWN( sini <= smax, "Error in OdeGearControl: sini is greater than smax" ); CPPAD_ASSERT_KNOWN( size_t(eabs.size()) == n, "Error in OdeGearControl: size of eabs is not equal to n" ); CPPAD_ASSERT_KNOWN( size_t(maxabs.size()) == n, "Error in OdeGearControl: size of maxabs is not equal to n" ); // some constants const Scalar zero(0); const Scalar one(1); const Scalar one_plus( Scalar(3) / Scalar(2) ); const Scalar two(2); const Scalar ten(10); // temporary indices size_t i, k; // temporary Scalars Scalar step, sprevious, lambda, axi, a, root, r; // vectors of Scalars Vector T (M + 1); Vector X( (M + 1) * n ); Vector e(n); Vector xf(n); // initial integer values size_t m = 1; nstep = 0; // initialize T T[0] = ti; // initialize X, ef, maxabs for(i = 0; i < n; i++) for(i = 0; i < n; i++) { X[i] = xi[i]; ef[i] = zero; X[i] = xi[i]; if( zero <= xi[i] ) maxabs[i] = xi[i]; else maxabs[i] = - xi[i]; } // initial step size step = smin; while( T[m-1] < tf ) { sprevious = step; // check maximum if( smax <= step ) step = smax; // check minimum if( m < M ) { if( step <= sini ) step = sini; } else if( step <= smin ) step = smin; // check if near the end if( tf <= T[m-1] + one_plus * step ) T[m] = tf; else T[m] = T[m-1] + step; // try using this step size nstep++; OdeGear(F, m, n, T, X, e); step = T[m] - T[m-1]; // compute value of lambda for this step lambda = Scalar(10) * sprevious / step; for(i = 0; i < n; i++) { axi = X[m * n + i]; if( axi <= zero ) axi = - axi; a = eabs[i] + erel * axi; if( e[i] > zero ) { if( m == 1 ) root = (a / e[i]) / ten; else { r = ( a / e[i] ) * step / (tf - ti); root = exp( log(r) / Scalar(m-1) ); } if( root <= lambda ) lambda = root; } } bool advance; if( m == M ) advance = one <= lambda || step <= one_plus * smin; else advance = one <= lambda || step <= one_plus * sini; if( advance ) { // accept the results of this time step CPPAD_ASSERT_UNKNOWN( m <= M ); if( m == M ) { // shift for next step for(k = 0; k < m; k++) { T[k] = T[k+1]; for(i = 0; i < n; i++) X[k*n + i] = X[(k+1)*n + i]; } } // update ef and maxabs for(i = 0; i < n; i++) { ef[i] = ef[i] + e[i]; axi = X[m * n + i]; if( axi <= zero ) axi = - axi; if( axi > maxabs[i] ) maxabs[i] = axi; } if( m != M ) m++; // all we need do in this case } // new step suggested by error criteria step = std::min(lambda , ten) * step / two; } for(i = 0; i < n; i++) xf[i] = X[(m-1) * n + i]; return xf; } } // End CppAD namespace # endif TMB/inst/include/cppad/rosen_34.hpp0000644000176200001440000003216414536067013016543 0ustar liggesusers/* $Id$ */ # ifndef CPPAD_ROSEN_34_INCLUDED # define CPPAD_ROSEN_34_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the GNU General Public License Version 3. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Rosen34$$ $spell cppad.hpp bool xf templated const Rosenbrock CppAD xi ti tf Karp Rosen Shampine ind dep $$ $index Rosen34$$ $index ODE, Rosenbrock$$ $index Rosenbrock, ODE$$ $index solve, ODE$$ $index stiff, ODE$$ $index differential, equation$$ $index equation, differential$$ $section A 3rd and 4th Order Rosenbrock ODE Solver$$ $head Syntax$$ $codei%# include %$$ $icode%xf% = Rosen34(%F%, %M%, %ti%, %tf%, %xi%) %$$ $icode%xf% = Rosen34(%F%, %M%, %ti%, %tf%, %xi%, %e%) %$$ $head Description$$ This is an embedded 3rd and 4th order Rosenbrock ODE solver (see Section 16.6 of $cref/Numerical Recipes/Bib/Numerical Recipes/$$ for a description of Rosenbrock ODE solvers). In particular, we use the formulas taken from page 100 of $cref/Shampine, L.F./Bib/Shampine, L.F./$$ (except that the fraction 98/108 has been correction to be 97/108). $pre $$ We use $latex n$$ for the size of the vector $icode xi$$. Let $latex \B{R}$$ denote the real numbers and let $latex F : \B{R} \times \B{R}^n \rightarrow \B{R}^n$$ be a smooth function. The return value $icode xf$$ contains a 5th order approximation for the value $latex X(tf)$$ where $latex X : [ti , tf] \rightarrow \B{R}^n$$ is defined by the following initial value problem: $latex \[ \begin{array}{rcl} X(ti) & = & xi \\ X'(t) & = & F[t , X(t)] \end{array} \] $$ If your set of ordinary differential equations are not stiff an explicit method may be better (perhaps $cref Runge45$$.) $head Include$$ The file $code cppad/rosen_34.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head xf$$ The return value $icode xf$$ has the prototype $codei% %Vector% %xf% %$$ and the size of $icode xf$$ is equal to $icode n$$ (see description of $cref/Vector/Rosen34/Vector/$$ below). $latex \[ X(tf) = xf + O( h^5 ) \] $$ where $latex h = (tf - ti) / M$$ is the step size. If $icode xf$$ contains not a number $cref nan$$, see the discussion of $cref/f/Rosen34/Fun/Nan/$$. $head Fun$$ The class $icode Fun$$ and the object $icode F$$ satisfy the prototype $codei% %Fun% &%F% %$$ This must support the following set of calls $codei% %F%.Ode(%t%, %x%, %f%) %F%.Ode_ind(%t%, %x%, %f_t%) %F%.Ode_dep(%t%, %x%, %f_x%) %$$ $subhead t$$ In all three cases, the argument $icode t$$ has prototype $codei% const %Scalar% &%t% %$$ (see description of $cref/Scalar/Rosen34/Scalar/$$ below). $subhead x$$ In all three cases, the argument $icode x$$ has prototype $codei% const %Vector% &%x% %$$ and has size $icode n$$ (see description of $cref/Vector/Rosen34/Vector/$$ below). $subhead f$$ The argument $icode f$$ to $icode%F%.Ode%$$ has prototype $codei% %Vector% &%f% %$$ On input and output, $icode f$$ is a vector of size $icode n$$ and the input values of the elements of $icode f$$ do not matter. On output, $icode f$$ is set equal to $latex F(t, x)$$ (see $icode F(t, x)$$ in $cref/Description/Rosen34/Description/$$). $subhead f_t$$ The argument $icode f_t$$ to $icode%F%.Ode_ind%$$ has prototype $codei% %Vector% &%f_t% %$$ On input and output, $icode f_t$$ is a vector of size $icode n$$ and the input values of the elements of $icode f_t$$ do not matter. On output, the $th i$$ element of $icode f_t$$ is set equal to $latex \partial_t F_i (t, x)$$ (see $icode F(t, x)$$ in $cref/Description/Rosen34/Description/$$). $subhead f_x$$ The argument $icode f_x$$ to $icode%F%.Ode_dep%$$ has prototype $codei% %Vector% &%f_x% %$$ On input and output, $icode f_x$$ is a vector of size $icode%n%*%n%$$ and the input values of the elements of $icode f_x$$ do not matter. On output, the [$icode%i%*%n%+%j%$$] element of $icode f_x$$ is set equal to $latex \partial_{x(j)} F_i (t, x)$$ (see $icode F(t, x)$$ in $cref/Description/Rosen34/Description/$$). $subhead Nan$$ If any of the elements of $icode f$$, $icode f_t$$, or $icode f_x$$ have the value not a number $code nan$$, the routine $code Rosen34$$ returns with all the elements of $icode xf$$ and $icode e$$ equal to $code nan$$. $subhead Warning$$ The arguments $icode f$$, $icode f_t$$, and $icode f_x$$ must have a call by reference in their prototypes; i.e., do not forget the $code &$$ in the prototype for $icode f$$, $icode f_t$$ and $icode f_x$$. $subhead Optimization$$ Every call of the form $codei% %F%.Ode_ind(%t%, %x%, %f_t%) %$$ is directly followed by a call of the form $codei% %F%.Ode_dep(%t%, %x%, %f_x%) %$$ where the arguments $icode t$$ and $icode x$$ have not changed between calls. In many cases it is faster to compute the values of $icode f_t$$ and $icode f_x$$ together and then pass them back one at a time. $head M$$ The argument $icode M$$ has prototype $codei% size_t %M% %$$ It specifies the number of steps to use when solving the differential equation. This must be greater than or equal one. The step size is given by $latex h = (tf - ti) / M$$, thus the larger $icode M$$, the more accurate the return value $icode xf$$ is as an approximation for $latex X(tf)$$. $head ti$$ The argument $icode ti$$ has prototype $codei% const %Scalar% &%ti% %$$ (see description of $cref/Scalar/Rosen34/Scalar/$$ below). It specifies the initial time for $icode t$$ in the differential equation; i.e., the time corresponding to the value $icode xi$$. $head tf$$ The argument $icode tf$$ has prototype $codei% const %Scalar% &%tf% %$$ It specifies the final time for $icode t$$ in the differential equation; i.e., the time corresponding to the value $icode xf$$. $head xi$$ The argument $icode xi$$ has the prototype $codei% const %Vector% &%xi% %$$ and the size of $icode xi$$ is equal to $icode n$$. It specifies the value of $latex X(ti)$$ $head e$$ The argument $icode e$$ is optional and has the prototype $codei% %Vector% &%e% %$$ If $icode e$$ is present, the size of $icode e$$ must be equal to $icode n$$. The input value of the elements of $icode e$$ does not matter. On output it contains an element by element estimated bound for the absolute value of the error in $icode xf$$ $latex \[ e = O( h^4 ) \] $$ where $latex h = (tf - ti) / M$$ is the step size. $head Scalar$$ The type $icode Scalar$$ must satisfy the conditions for a $cref NumericType$$ type. The routine $cref CheckNumericType$$ will generate an error message if this is not the case. In addition, the following operations must be defined for $icode Scalar$$ objects $icode a$$ and $icode b$$: $table $bold Operation$$ $cnext $bold Description$$ $rnext $icode%a% < %b%$$ $cnext less than operator (returns a $code bool$$ object) $tend $head Vector$$ The type $icode Vector$$ must be a $cref SimpleVector$$ class with $cref/elements of type Scalar/SimpleVector/Elements of Specified Type/$$. The routine $cref CheckSimpleVector$$ will generate an error message if this is not the case. $head Parallel Mode$$ $index parallel, Rosen34$$ $index Rosen34, parallel$$ For each set of types $cref/Scalar/Rosen34/Scalar/$$, $cref/Vector/Rosen34/Vector/$$, and $cref/Fun/Rosen34/Fun/$$, the first call to $code Rosen34$$ must not be $cref/parallel/ta_in_parallel/$$ execution mode. $head Example$$ $children% example/rosen_34.cpp %$$ The file $cref rosen_34.cpp$$ contains an example and test a test of using this routine. It returns true if it succeeds and false otherwise. $head Source Code$$ The source code for this routine is in the file $code cppad/rosen_34.hpp$$. $end -------------------------------------------------------------------------- */ # include # include # include # include # include # include # include // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL # include namespace CppAD { // BEGIN CppAD namespace template Vector Rosen34( Fun &F , size_t M , const Scalar &ti , const Scalar &tf , const Vector &xi ) { Vector e( xi.size() ); return Rosen34(F, M, ti, tf, xi, e); } template Vector Rosen34( Fun &F , size_t M , const Scalar &ti , const Scalar &tf , const Vector &xi , Vector &e ) { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; // check numeric type specifications CheckNumericType(); // check simple vector class specifications CheckSimpleVector(); // Parameters for Shampine's Rosenbrock method // are static to avoid recalculation on each call and // do not use Vector to avoid possible memory leak static Scalar a[3] = { Scalar(0), Scalar(1), Scalar(3) / Scalar(5) }; static Scalar b[2 * 2] = { Scalar(1), Scalar(0), Scalar(24) / Scalar(25), Scalar(3) / Scalar(25) }; static Scalar ct[4] = { Scalar(1) / Scalar(2), - Scalar(3) / Scalar(2), Scalar(121) / Scalar(50), Scalar(29) / Scalar(250) }; static Scalar cg[3 * 3] = { - Scalar(4), Scalar(0), Scalar(0), Scalar(186) / Scalar(25), Scalar(6) / Scalar(5), Scalar(0), - Scalar(56) / Scalar(125), - Scalar(27) / Scalar(125), - Scalar(1) / Scalar(5) }; static Scalar d3[3] = { Scalar(97) / Scalar(108), Scalar(11) / Scalar(72), Scalar(25) / Scalar(216) }; static Scalar d4[4] = { Scalar(19) / Scalar(18), Scalar(1) / Scalar(4), Scalar(25) / Scalar(216), Scalar(125) / Scalar(216) }; CPPAD_ASSERT_KNOWN( M >= 1, "Error in Rosen34: the number of steps is less than one" ); CPPAD_ASSERT_KNOWN( e.size() == xi.size(), "Error in Rosen34: size of e not equal to size of xi" ); size_t i, j, k, l, m; // indices size_t n = xi.size(); // number of components in X(t) Scalar ns = Scalar(double(M)); // number of steps as Scalar object Scalar h = (tf - ti) / ns; // step size Scalar zero = Scalar(0); // some constants Scalar one = Scalar(1); Scalar two = Scalar(2); // permutation vectors needed for LU factorization routine CppAD::vector ip(n), jp(n); // vectors used to store values returned by F Vector E(n * n), Eg(n), f_t(n); Vector g(n * 3), x3(n), x4(n), xf(n), ftmp(n), xtmp(n), nan_vec(n); // initialize e = 0, nan_vec = nan for(i = 0; i < n; i++) { e[i] = zero; nan_vec[i] = nan(zero); } xf = xi; // initialize solution for(m = 0; m < M; m++) { // time at beginning of this interval Scalar t = ti * (Scalar(int(M - m)) / ns) + tf * (Scalar(int(m)) / ns); // value of x at beginning of this interval x3 = x4 = xf; // evaluate partial derivatives at beginning of this interval F.Ode_ind(t, xf, f_t); F.Ode_dep(t, xf, E); // E = f_x if( hasnan(f_t) || hasnan(E) ) { e = nan_vec; return nan_vec; } // E = I - f_x * h / 2 for(i = 0; i < n; i++) { for(j = 0; j < n; j++) E[i * n + j] = - E[i * n + j] * h / two; E[i * n + i] += one; } // LU factor the matrix E # ifndef NDEBUG int sign = LuFactor(ip, jp, E); # else LuFactor(ip, jp, E); # endif CPPAD_ASSERT_KNOWN( sign != 0, "Error in Rosen34: I - f_x * h / 2 not invertible" ); // loop over integration steps for(k = 0; k < 3; k++) { // set location for next function evaluation xtmp = xf; for(l = 0; l < k; l++) { // loop over previous function evaluations Scalar bkl = b[(k-1)*2 + l]; for(i = 0; i < n; i++) { // loop over elements of x xtmp[i] += bkl * g[i*3 + l] * h; } } // ftmp = F(t + a[k] * h, xtmp) F.Ode(t + a[k] * h, xtmp, ftmp); if( hasnan(ftmp) ) { e = nan_vec; return nan_vec; } // Form Eg for this integration step for(i = 0; i < n; i++) Eg[i] = ftmp[i] + ct[k] * f_t[i] * h; for(l = 0; l < k; l++) { for(i = 0; i < n; i++) Eg[i] += cg[(k-1)*3 + l] * g[i*3 + l]; } // Solve the equation E * g = Eg LuInvert(ip, jp, E, Eg); // save solution and advance x3, x4 for(i = 0; i < n; i++) { g[i*3 + k] = Eg[i]; x3[i] += h * d3[k] * Eg[i]; x4[i] += h * d4[k] * Eg[i]; } } // Form Eg for last update to x4 only for(i = 0; i < n; i++) Eg[i] = ftmp[i] + ct[3] * f_t[i] * h; for(l = 0; l < 3; l++) { for(i = 0; i < n; i++) Eg[i] += cg[2*3 + l] * g[i*3 + l]; } // Solve the equation E * g = Eg LuInvert(ip, jp, E, Eg); // advance x4 and accumulate error bound for(i = 0; i < n; i++) { x4[i] += h * d4[3] * Eg[i]; // cant use abs because cppad.hpp may not be included Scalar diff = x4[i] - x3[i]; if( diff < zero ) e[i] -= diff; else e[i] += diff; } // advance xf for this step using x4 xf = x4; } return xf; } } // End CppAD namespace # endif TMB/inst/include/convenience.hpp0000644000176200001440000001310514536067013016306 0ustar liggesusers// Copyright (C) 2013-2015 Kasper Kristensen // License: GPL-2 /** \file \brief Templates to get convenient R-like syntax. */ /** \brief Similar to R's split function: split(x,fac) devides x into groups defined by fac . * \details Returns a "vector of vectors". */ template vector > split(vector x, vector fac) { if (x.size() != fac.size()) Rf_error("x and fac must have equal length."); int nlevels = 0; for (int i = 0; i < fac.size(); i++) if (fac[i] >= nlevels) nlevels = fac[i] + 1; vector > ans(nlevels); vector lngt(nlevels); lngt.setZero(); for (int i = 0; i < fac.size(); i++) lngt[fac[i]]++; for (int i = 0; i < nlevels; i++) ans[i].resize(lngt[i]); lngt.setZero(); for (int i = 0; i < fac.size(); i++) { ans[fac[i]][lngt[fac[i]]] = x[i]; lngt[fac[i]]++; } return ans; } /** Sum of vector, matrix or array */ template