[Rcpp-commits] r2730 - pkg/RcppDE/inst/doc
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Mon Dec 6 05:27:53 CET 2010
Author: edd
Date: 2010-12-06 05:27:53 +0100 (Mon, 06 Dec 2010)
New Revision: 2730
Modified:
pkg/RcppDE/inst/doc/RcppDE.tex
Log:
some more vignette updates
Modified: pkg/RcppDE/inst/doc/RcppDE.tex
===================================================================
--- pkg/RcppDE/inst/doc/RcppDE.tex 2010-12-06 02:45:44 UTC (rev 2729)
+++ pkg/RcppDE/inst/doc/RcppDE.tex 2010-12-06 04:27:53 UTC (rev 2730)
@@ -133,36 +133,36 @@
functionality is provided by three \proglang{R} files, as well as three
\proglang{C} files.
-Table~\ref{tab:Rfiles} lists the files and corresponding key functions:
+Many more changes were made to the \proglang{C} files: besides the obvious
+porting from \proglang{C} to \proglang{C++}, several internal code changes
+were made. The overall architecture and API remained as unchanged as
+possible.
+%
+On the other hand, very few changes were required at the \proglang{R}
+level. The user-facing side of \pkg{DEoptim} persists virtually unchanged.
-\begin{table}[htb]
- \begin{center}
- \begin{tabular}{lr}
- \toprule
- File & Functions \\
-% \cmidrule{2}
- \verb|DEoptim.R| \phantom{XXXXXXXXX} & \verb|DEoptim()| \\
- & \verb|DEoptim.control()| \\[6pt]
- \verb|methods.R| & \verb|summary.DEoptim()| \\
- & \verb|plot.DEoptim()| \\[6pt]
- \verb|zzz.R| & \verb|.onLoad()| \\
- \bottomrule
- \end{tabular}
- \caption{Source file organisation for \proglang{R} files in \pkg{DEoptim}
- and \pkg{RcppDE}}
- \label{tab:Rfiles}
- \end{center}
-\end{table}
+Because of the dominant number of changes at the level of the compiled
+language, we discuss the structure, and later on changes, first before
+turning to the \proglang{R} side.
-Very few changes has to made for \pkg{RcppDE} as keeping the interface
-compatible was an important goal. As can be seen from table~\ref{tab:Rfiles},
-no files or functions were added. A more detailed comparison follow below
-in section~\ref{sec:Rchanges}.
+\subsection[C / C++ structure and changes]{\proglang{} / \proglang{C++} structure and changes}
-Similarly, table~\ref{tab:Cfiles} lists the \proglang{C} and \proglang{C++}
-files in \pkg{DEoptim} and \pkg{RcppDE}, respectively:
+Table~\ref{tab:Cfiles} lists the \proglang{C} and \proglang{C++}
+files in \pkg{DEoptim} and \pkg{RcppDE}, respectively.
+The large file \verb|de4_0.c| has been split into three files: one each for
+the core functions \verb|DEoptim()| (which is called from \proglang{R}),
+\verb|devol()| (which is the core differential evolution optimisation
+routine) and \verb|permute()| (which is a helper function used to shuffle
+indices).
-\begin{table}[htb]
+The evalution function has been replaced by a base class and two virtual
+classes. These can now use of an objective function written in \proglang{R}
+(as in \pkg{DEoptim}) as well as one written in \proglang{C++} which can lead
+to substantial speed improvements. Section~\ref{sec:Cppchanges} discusses
+these changes in more detail.
+
+
+\begin{table}[tb]
\begin{center}
\begin{tabular}{lrclr}
\toprule
@@ -174,8 +174,8 @@
& \verb|devol()| & & \verb|devol.cpp| & \verb|devol()| \\
& \verb|permute()| & & \verb|permute.cpp| & \verb|permute()| \\[6pt]
\verb|evaluate.c|& \verb|evaluate()| & & & \\[6pt]
- & & & \verb|evaluate.h|& \phantom{XX} \verb|EvalBase class| \\[6pt]
- \verb|get_element.c|\phantom{XX} & \verb|getListElement()| & \phantom{XXXX} & & \\
+ & & & \verb|evaluate.h|& \phantom{X} \verb|EvalBase class| \\[6pt]
+ \verb|get_element.c|\phantom{X} & \verb|getListElement()| & \phantom{X} & & \\
\bottomrule
\end{tabular}
\caption{Source file organisation for \proglang{C} files in \pkg{DEoptim}}
@@ -183,308 +183,249 @@
\end{center}
\end{table}
-The large file \verb|de4_0.c| has been split into three files: one each for
-the core functions \verb|DEoptim()| (which is called from \proglang{R}),
-\verb|devol()| (which is the core differential evolution optimisation
-routine) and \verb|permute()| (which is a helper function used to shuffle
-indices). The evalution function has been replaced by a base class and two
-virtual classes. These use of an objective function written in \proglang{R}
-(as in \pkg{DEoptim}) as well as in \proglang{C++} which can lead to
-substantial speed improvements.
-Section~\ref{sec:Cppchanges} discusses these changes in more detail.
+\subsection[R structure and changes]{\proglang{R} structure and changes}
-\section[R changes]{\proglang{R} changes}
-\label{sec:Rchanges}
+Table~\ref{tab:Rfiles} lists the files and corresponding key functions. Very
+few changes has to made for \pkg{RcppDE} as keeping the interface compatible
+was an important goal. As can be seen from table~\ref{tab:Rfiles}, no files
+or functions were added. A more detailed comparison follow below in
+section~\ref{sec:Rchanges}.
-TBD
+\begin{table}[tb]
+ \begin{center}
+ \begin{tabular}{lr}
+ \toprule
+ File & Functions \\
+ \midrule
+% \cmidrule{2}
+ \verb|DEoptim.R| \phantom{XXXXX} & \verb|DEoptim()| \\
+ & \verb|DEoptim.control()| \\[6pt]
+ \verb|methods.R| & \verb|summary.DEoptim()| \\
+ & \verb|plot.DEoptim()| \\[6pt]
+ \verb|zzz.R| & \verb|.onLoad()| \\
+ \bottomrule
+ \end{tabular}
+ \caption{Source file organisation for \proglang{R} files in \pkg{DEoptim}
+ and \pkg{RcppDE}}
+ \label{tab:Rfiles}
+ \end{center}
+\end{table}
-\section[C++ changes]{\proglang{C++} changes}
+
+\section[C / C++ changes]{\proglang{C} / \proglang{C++} changes}
\label{sec:Cppchanges}
+In this section, we will look at the changes at the \proglang{C} /
+\proglang{C++} level. Figures~\ref{fig:deoptim_start} to
+\ref{fig:deoptim_end} contain the code the highest-level \proglang{C++}
+function: \verb|DEoptim()| (which we renamed from \verb|DEoptim_C()| as there
+is no need for a different name at the \proglang{C} level relative to
+\proglang{R}). This is followed by figures~\ref{fig:devol_start} to
+\ref{fig:devol_return} on the main worker function \verb|devol()| before
+figure~\ref{fig:evaluate_fun} compares the objective function evaluation of
+as the last element at the \proglang{C} / \proglang{C++} level.
+
\subsection[de4_0.c and deoptim.cpp]{\code{de4\_0.c} and \code{deoptim.cpp}}
-\subsection[de4_0.c and devol.cpp]{\code{de4\_0.c} and \code{devol.cpp}}
+The \verb|DEoptim()| function (renamed from \verb|DEoptim_C()| as there is no need for a different
+name at the \proglang{C} level relative to \proglang{R}) is the entry point
+from \proglang{R}. It receives parameters, sets up the call of \verb|devol()|
+and then prepares the return values.
-\subsection[Evaluation functions in R and C++]{Evaluation functions in \proglang{R} and \proglang{C++}}
+\paragraph{Part 1: Start of \texttt{DEoptim()}} The first part concerns
+itself with receiving parameters from \proglang{R};
+figure~\ref{fig:devol_start} displays this. The pure mechanics of passing and
+receiving parameters from \proglang{R} are easier thanks to logic provided by
+the \pkg{Rcpp} package:
+\begin{enumerate}
+\item Figure~\ref{fig:deoptim_start} illustrates this point: Panel B (with code
+ using \proglang{C++}) appears to be about half the size of panel A but this
+ due in part to bringing comments on the same line as code.
+\item However, instead of using a mix of macros like \verb|NUMERIC_VALUE|,
+ \verb|INTEGER_VALUE|, \texttt{NUMERIC\_POINTER} and so on, we have consistent
+ use of \pkg{Rcpp} template function \verb|as| with template types
+ corresponding to base typed \verb|int|, \verb|double| etc. Also of note is
+ how one matrix object (for an initial population of parameter values) is
+ initialized directly from a parameter.
+\item Paremeter lookup is by a string value but done using \pkg{Rcpp} lookup
+ of elements in the \verb|list| type (which corresponds to the \proglang{R}
+ list passed in) rather than via a (similar but ad-hoc) function
+ \verb|getListElement| that hence is not longer needed in \pkg{RcppDE}.
+\item Here as in later code examples, care was taken to ensure that variable
+ names and types correpond closely between both variants.
+\end{enumerate}
-\section{Auxiliary files}
+\paragraph{Part 2: Middle of \texttt{DEoptim()}} The second part,
+displayed in figure~\ref{fig:deoptim_memory}, allocates dynamic memory for
+both paraneters returned to \proglang{R} as well as for temporary objects
+required to store the results of intermediate computations. Again, panel A
+shows the \proglang{C} code from \pkg{Rcpp} whereas panel B displays the
+\proglang{C++} code. One difference becomes immediately apparent: the lack
+of proper matrix or vector types in \proglang{C}. We use the classes from the
+\pkg{Armadillo} \proglang{C++} library written by
+\cite{Sanderson:2010:Armadillo} and provided via the \proglang{R} package
+\pkg{Armadillo} by \citet{CRAN:RcppArmadillo}.
+\begin{enumerate}
+\item Matrix objects are created in \proglang{C} by first allocating a vector
+ of pointers to pointers, which is followed by a loop in which each each
+ column is allocated as vector of approrpriate length.
+\item In \proglang{C++}, allocating a matrix is a single statement. Memory is
+ managed by reference counting and is freed when objects go out of
+ scope. This removes a \textsl{significant} portion of programmer errors.
+\item Another subtle difference is in the allocations of the container
+ holding different population snapshots, here called \texttt{d\_storepop}:
+ \pkg{Rcpp} lets us create a list object in which we store matrices, just as
+ would in \proglang{R} whereas the \proglang{C} construct is much more
+ complicated as we will see below.
+\end{enumerate}
-\section{Performance}
+\paragraph{Part 3: End of \texttt{DEoptim()}} The third and last part of
+\verb|DEoptim()| covers the actual call of the worker function \verb|devol()|
+and the preparation of return values for \proglang{R}.
-\section{Summary}
+\begin{enumerate}
+\item The \verb|devol()| function is called: as we aim to maintainer
+ interfaces, the is unchanged between both approaches shown in
+ figure~\ref{fig:deoptim_end}.
+\item The code following the function call is very different. The new
+ version saves in at least three ways:
+ \begin{enumerate}
+ \item No need to create new temporary variables just to convert to
+ \texttt{SEXP} types for return to \proglang{R} as the \pkg{Rcpp} takes
+ care of this.
+ \item No need to allocate memory for new temporary variables (as we do not
+ need these variables, and even if we did memory allocation would be implicit).
+ \item No need to \texttt{PROTECT} and later \texttt{UNPROTECT} such dynamoc
+ memory allocations (because this is handled automatically behind the scenes).
+ \item No need for an explicit new list object to hold the eight return variables.
+ \item No need to (explicitly) assign names for these eight return
+ variables.
+ \end{enumerate}
+\item Rather, a mere two statements are executed: the call to \verb|devol()|
+ followed by single call to create a return object as a list with named
+ elements which are simply inserted---just like we would in \proglang{R} itself.
+\item The remaining code takes care of exception handling by providing to
+ \verb|catch()| branches. These either forward a recognised exception to
+ \proglang{R} or in case of recognised exception signal a generic error.
+\end{enumerate}
-\bibliography{RcppDE}
+In sum, we see how a number of (possibly small) enhancements taken together
+permit us to a function which is considerably shorter and easier to read, yet
+fully equivalent in terms of its functionality.
+\subsection[de4_0.c and devol.cpp]{\code{de4\_0.c} and \code{devol.cpp}}
-\section*{Appendix}
+The \verb|devol()| function is the key part of the \pkg{DEoptim}
+implementation. It is also by far the largest function. We will discuss it
+again in different sections, each corresponding to one figure ranging from
+figure~\ref{fig:devol_start} to figure~\ref{fig:devol_return}.
-%% R functions
+\paragraph{Part 1: Start of \texttt{devol()}} The first part concerns the
+beginning of the \verb|devol()|. The display (in
+figure~\ref{fig:devol_start}) of panels A and B differs mostly in minor
+ascpects:
+\begin{enumerate}
+\item The \proglang{C} version contains a declaration of a number of loop
+ variable that are either not needed at all in the \proglang{C++} version,
+ or declared locally.
+\item The urn depth is defined as a \proglang{C} macro and a constant
+ variable, respectively.
+\item The \proglang{C++} version has an additional short block to set up the
+ proper evaluation class for the user supplied function, depending on
+ whether an external pointer object is passed (in which case we expect a
+ compiled functin) or not in which case an \proglang{R} routine is used,
+ just like in \pkg{DEoptim}.
+\end{enumerate}
-\begin{sidewaysfigure} % fig R1: beginning of DEoptim()
- \begin{minipage}{0.48\linewidth}
- \tiny
- \begin{CodeChunk}
- \begin{CodeInput}
-DEoptim <- function(fn, lower, upper, control = DEoptim.control(), ...) {
- fn1 <- function(par) fn(par, ...)
- if (length(lower) != length(upper))
- stop("'lower' and 'upper' are not of same length")
- if (!is.vector(lower))
- lower <- as.vector(lower)
- if (!is.vector(upper))
- upper <- as.vector(upper)
- if (any(lower > upper))
- stop("'lower' > 'upper'")
- if (any(lower == "Inf"))
- warning("you set a component of 'lower' to 'Inf'. May imply 'NaN' results", immediate. = TRUE)
- if (any(lower == "-Inf"))
- warning("you set a component of 'lower' to '-Inf'. May imply 'NaN' results", immediate. = TRUE)
- if (any(upper == "Inf"))
- warning("you set a component of 'upper' to 'Inf'. May imply 'NaN' results", immediate. = TRUE)
- if (any(upper == "-Inf"))
- warning("you set a component of 'upper' to '-Inf'. May imply 'NaN' results", immediate. = TRUE)
- if (!is.null(names(lower)))
- nam <- names(lower)
- else if (!is.null(names(upper)) & is.null(names(lower)))
- nam <- names(upper)
- else
- nam <- paste("par", 1:length(lower), sep = "")
+\paragraph{Part 2: Initializations in \texttt{devol()}} The second part of
+\verb|devol()| deals with the creation and initialization of a number of
+variables. The \proglang{C} language code in panel A is vastly more verbose
+and longer than the \proglang{C++} code in panel B. As shown in
+figure~\ref{fig:devol_init}, key differences are:
+\begin{enumerate}
+\item Initialization of matrices to zero values uses two explicit loops in
+ the \proglang{C} version.\footnote{The \texttt{memset()} function could be
+ used in the \proglang{C} version ot avoid the loops for a direct
+ performance gain.} In \proglang{C++}, we simply use the member function
+ \verb|zeros()| provided by the \pkg{Armadillo} library.
+\item In panel B for the \proglang{C++} case, the initial population in
+ variable \texttt{initialpopm} is transposed in the \proglang{C++}
+ example. We keep each population as a \textsl{column} rather than a
+ \textsl{row} as memory can generally be accessed faster column-wise.
+\item The actual initialization of the first population is very comparable;
+ in particular the \proglang{R} random number generator is called in the
+ exact same sequence so that results are in fact identical.
+\item The initial population evaluation occurs with a call to
+ \verb|evaluate()| in the original version, and a call of the member
+ function of the evaluation class which will call either the supplied
+ compiled function, or the supplied \proglang{R} functions.
+\end{enumerate}
- ctrl <- do.call(DEoptim.control, as.list(control))
- ctrl$npar <- length(lower)
- if (ctrl$NP < 4) {
- warning("'NP' < 4; set to default value 50\n", immediate. = TRUE)
- ctrl$NP <- 50
- }
- if (ctrl$NP < 10*length(lower))
- warning("For many problems it is best to set 'NP' (in 'control') to be at least "
- "ten times the length of the parameter vector. \n", immediate. = TRUE)
- if (!is.null(ctrl$initialpop)) {
- ctrl$specinitialpop <- TRUE
- if(!identical(as.numeric(dim(ctrl$initialpop)), c(ctrl$NP, ctrl$npar)))
- stop("Initial population is not a matrix with dim. NP x length(upper).")
- }
- else {
- ctrl$specinitialpop <- FALSE
- ctrl$initialpop <- 0.0
- }
- ##
- ctrl$trace <- as.numeric(ctrl$trace)
- ctrl$specinitialpop <- as.numeric(ctrl$specinitialpop)
- ctrl$initialpop <- as.numeric(ctrl$initialpop)
- \end{CodeInput}
- \end{CodeChunk}
+\paragraph{Part 3: Iteration loop setup and start of population loop in \texttt{devol()}}
- \normalsize
- \centering{Panel A: \proglang{R} version in \pkg{DEoptim}}
- \tiny
+The next part of \verb|devol()|, shown in
+figure~\ref{fig:devol_iter}, is already inside the large outer loop over all iterations.
- \end{minipage}
- \begin{minipage}{0.03\linewidth}
- \phantom{XX}
- \end{minipage}
- \begin{minipage}{0.48\linewidth}
- \tiny
+Similar to the discussion above, the new code is shorter in large part of
+more compact matrix expressions. Other difference are:
+\begin{enumerate}
+\item Intermediate populations are stored directly in a list, after being
+ transposed to account for our design choice of operating column-wise. In
+ the \proglang{C} code, the matrices are somewhat awkwardly `serialised'
+ into a single vector using a counter that incremened position by position.
+\item Several other vector copies are excecuted in a single statement rather
+ than in an explicit loop.
+\item At the beginning of the population loop, a vector is once more stored
+ in a temporary variable and the permuation algoritm is called to pick
+ suitable indices which will be used next.
+\end{enumerate}
- \begin{CodeChunk}
- \begin{CodeInput}
-DEoptim <- function(fn, lower, upper, control = DEoptim.control(), env, ...) {
- ##fn1 <- function(par) fn(par, ...)
- if (length(lower) != length(upper))
- stop("'lower' and 'upper' are not of same length")
- if (!is.vector(lower))
- lower <- as.vector(lower)
- if (!is.vector(upper))
- upper <- as.vector(upper)
- if (any(lower > upper))
- stop("'lower' > 'upper'")
- if (any(lower == "Inf"))
- warning("you set a component of 'lower' to 'Inf'. May imply 'NaN' results", immediate. = TRUE)
- if (any(lower == "-Inf"))
- warning("you set a component of 'lower' to '-Inf'. May imply 'NaN' results", immediate. = TRUE)
- if (any(upper == "Inf"))
- warning("you set a component of 'upper' to 'Inf'. May imply 'NaN' results", immediate. = TRUE)
- if (any(upper == "-Inf"))
- warning("you set a component of 'upper' to '-Inf'. May imply 'NaN' results", immediate. = TRUE)
- if (!is.null(names(lower)))
- nam <- names(lower)
- else if (!is.null(names(upper)) & is.null(names(lower)))
- nam <- names(upper)
- else
- nam <- paste("par", 1:length(lower), sep = "")
- if (missing(env))
- env <- new.env()
+\paragraph{Part 4: First four population strategies in \texttt{devol()}}
- ctrl <- do.call(DEoptim.control, as.list(control))
- ctrl$npar <- length(lower)
- if (ctrl$NP < 4) {
- warning("'NP' < 4; set to default value 50\n", immediate. = TRUE)
- ctrl$NP <- 50
- }
- if (ctrl$NP < 10*length(lower))
- warning("For many problems it is best to set 'NP' (in 'control') to be at least ten"
- " times the length of the parameter vector. \n", immediate. = TRUE)
- if (!is.null(ctrl$initialpop)) {
- ctrl$specinitialpop <- TRUE
- if(!identical(as.numeric(dim(ctrl$initialpop)), c(ctrl$NP, ctrl$npar)))
- stop("Initial population is not a matrix with dim. NP x length(upper).")
- }
- else {
- ctrl$specinitialpop <- FALSE
- ctrl$initialpop <- matrix(0,1,1) # dummy matrix
- }
- ##
- ctrl$trace <- as.numeric(ctrl$trace)
- ctrl$specinitialpop <- as.numeric(ctrl$specinitialpop)
- \end{CodeInput}
- \end{CodeChunk}
-
- \normalsize
- \centering{Panel B: \proglang{R} version in \pkg{RcppDE}}
- \end{minipage}
- \caption{First half of \proglang{R} function \texttt{DEoptim()}}
- \label{fig:fig_R_DEoptim1}
-\end{sidewaysfigure}
+Evaluating each population member based on the user-selected strategies is
+detailed in figure~\ref{fig:devol_first_four}. There are only fairly minor differences
+between both version as shown by panels A and B:
+\begin{enumerate}
+\item Instead of \verb|if/else| branches, the new version uses a
+ \verb|switch| statement.
+\item The case-invariant initialization of \verb|k| has been moved before the
+ block.
+\end{enumerate}
-\begin{sidewaysfigure} % fig R2: second half of DEoptim()
- \begin{minipage}{0.48\linewidth}
- \tiny
- \begin{CodeChunk}
- \begin{CodeInput}
- outC <- .Call("DEoptimC", lower, upper, fn1, ctrl, new.env(),
- PACKAGE = "DEoptim")
- ##
- if (length(outC$storepop) > 0) {
- nstorepop <- floor((outC$iter - ctrl$storepopfrom) / ctrl$storepopfreq)
- storepop <- list()
- cnt <- 1
- for(i in 1:nstorepop) {
- idx <- cnt:((cnt - 1) + (ctrl$NP * ctrl$npar))
- storepop[[i]] <- matrix(outC$storepop[idx], nrow = ctrl$NP, ncol = ctrl$npar,
- byrow = TRUE)
- cnt <- cnt + (ctrl$NP * ctrl$npar)
- dimnames(storepop[[i]]) <- list(1:ctrl$NP, nam)
- }
- }
- else {
- storepop = NULL
- }
+\paragraph{Part 5: Remaining three population strategies in \texttt{devol()}}
- ## optim
- bestmem <- as.numeric(outC$bestmem)
- names(bestmem) <- nam
- bestval <- as.numeric(outC$bestval)
- nfeval <- as.numeric(outC$nfeval)
- iter <- as.numeric(outC$iter)
+For the three remaining strategies, the code in panels A and B of
+figure~\ref{fig:devol_other_three} is similar to the code in
+\ref{fig:devol_first_four}.
- ## member
- names(lower) <- names(upper) <- nam
- bestmemit <- matrix(outC$bestmemit, nrow = iter,
- ncol = ctrl$npar, byrow = TRUE)
+\paragraph{Part 6: End of population loop in \texttt{devol()}}
- dimnames(bestmemit) <- list(1:iter, nam)
- bestvalit <- as.numeric(outC$bestvalit[1:iter])
- pop <- matrix(outC$pop, nrow = ctrl$NP, ncol = ctrl$npar,
- byrow = TRUE)
- storepop <- as.list(storepop)
+Figure~\ref{fig:devol_end_pop}
- outR <- list(optim = list(
- bestmem = bestmem,
- bestval = bestval,
- nfeval = nfeval,
- iter = iter),
- member = list(
- lower = lower,
- upper = upper,
- bestmemit = bestmemit,
- bestvalit = bestvalit,
- pop = pop,
- storepop = storepop))
+\paragraph{Part 7: Special case of \texttt{bs} flag in \texttt{devol()}}
- attr(outR, "class") <- "DEoptim"
- return(outR)
-}
- \end{CodeInput}
- \end{CodeChunk}
+Figure~\ref{fig:devol_bs_flag}
- \normalsize
- \centering{Panel A: \proglang{R} version in \pkg{DEoptim}}
- \tiny
+\paragraph{Part 8: End of \texttt{devol()}}
- \end{minipage}
- \begin{minipage}{0.03\linewidth}
- \phantom{XX}
- \end{minipage}
- \begin{minipage}{0.48\linewidth}
- \tiny
+Figure~\ref{fig:devol_return}
- \begin{CodeChunk}
- \begin{CodeInput}
- outC <- .Call("DEoptim", lower, upper, fn, ctrl, env, PACKAGE = "RcppDE")
- ##
- if (length(outC$storepop) > 0) {
- nstorepop <- floor((outC$iter - ctrl$storepopfrom) / ctrl$storepopfreq)
- ## storepop <- list()
- ## cnt <- 1
- ## for(i in 1:nstorepop) {
- ## idx <- cnt:((cnt - 1) + (ctrl$NP * ctrl$npar))
- ## storepop[[i]] <- matrix(outC$storepop[idx], nrow = ctrl$NP, ncol = ctrl$npar,
- ## byrow = TRUE)
- ## cnt <- cnt + (ctrl$NP * ctrl$npar)
- ## dimnames(storepop[[i]]) <- list(1:ctrl$NP, nam)
- ## }
- storepop <- outC$storepop[1:nstorepop]
- for (i in 1:length(storepop)) dimnames(storepop[[i]]) <- list(1:ctrl$NP, nam)
- }
- else {
- storepop = NULL
- }
+\subsection[Evaluation functions in R and C++]{Evaluation functions in \proglang{R} and \proglang{C++}}
- ## optim
- bestmem <- as.numeric(outC$bestmem)
- names(bestmem) <- nam
- bestval <- as.numeric(outC$bestval)
- nfeval <- as.numeric(outC$nfeval)
- iter <- as.numeric(outC$iter)
+\section[R changes]{\proglang{R} changes}
+\label{sec:Rchanges}
- ## member
- names(lower) <- names(upper) <- nam
- #bestmemit <- matrix(outC$bestmemit, nrow = iter, ncol = ctrl$npar, byrow = TRUE)
- bestmemit <- outC$bestmemit
+\section{Auxiliary files}
- dimnames(bestmemit) <- list(1:iter, nam)
- bestvalit <- as.numeric(outC$bestvalit[1:iter])
- #pop <- matrix(outC$pop, nrow = ctrl$NP, ncol = ctrl$npar, byrow = TRUE)
- pop <- outC$pop
- storepop <- as.list(storepop)
+\section{Performance}
- outR <- list(optim = list(
- bestmem = bestmem,
- bestval = bestval,
- nfeval = nfeval,
- iter = iter),
- member = list(
- lower = lower,
- upper = upper,
- bestmemit = bestmemit,
- bestvalit = bestvalit,
- pop = pop,
- storepop = storepop))
+\section{Summary}
- attr(outR, "class") <- "DEoptim"
- return(outR)
-}
- \end{CodeInput}
- \end{CodeChunk}
-
- \normalsize
- \centering{Panel B: \proglang{R} version in \pkg{RcppDE}}
- \end{minipage}
- \caption{Second half of \proglang{R} function \texttt{DEoptim()}}
- \label{fig:fig_R_DEoptim2}
-\end{sidewaysfigure}
+\bibliography{RcppDE}
+\section*{Appendix}
+
%% C++ functions
\begin{sidewaysfigure} % fig 1: beginning of DEoptimC / DEoptim
@@ -589,7 +530,7 @@
\centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{Beginning of \code{DEoptim()} \proglang{C/C++} function}
- \label{fig:deoptim_start1}
+ \label{fig:deoptim_start}
\end{sidewaysfigure}
\begin{sidewaysfigure} % fig 2: memory allocations
@@ -926,7 +867,7 @@
\centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{\code{devol()} beginning}
- \label{fig:deoptim_end}
+ \label{fig:devol_start}
\end{sidewaysfigure}
@@ -1077,7 +1018,7 @@
\centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{\code{devol()} initializations}
- \label{fig:deoptim_end}
+ \label{fig:devol_init}
\end{sidewaysfigure}
@@ -1184,7 +1125,7 @@
\normalsize \centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{\code{devol()} iteration loop setup and beginning of population loop}
- \label{fig:deoptim_end}
+ \label{fig:devol_iter}
\end{sidewaysfigure}
@@ -1315,7 +1256,7 @@
\normalsize \centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{\code{devol()} first four strategy options}
- \label{fig:deoptim_end}
+ \label{fig:devol_first_four}
\end{sidewaysfigure}
@@ -1446,7 +1387,7 @@
\normalsize \centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{\code{devol()} remaining three strategy options}
- \label{fig:deoptim_end}
+ \label{fig:devol_other_three}
\end{sidewaysfigure}
@@ -1537,7 +1478,7 @@
\normalsize \centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{\code{devol()} remainder of population mutation loop}
- \label{fig:deoptim_end}
+ \label{fig:devol_end_pop}
\end{sidewaysfigure}
@@ -1638,7 +1579,7 @@
\normalsize \centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{\code{devol()} case of \code{i\_bs\_flag}}
- \label{fig:deoptim_end}
+ \label{fig:devol_bs_flag}
\end{sidewaysfigure}
@@ -1765,7 +1706,7 @@
\normalsize \centering{Panel B: \proglang{C++} version using \pkg{Rcpp}}
\end{minipage}
\caption{\code{devol()} population processing and return preparation}
- \label{fig:deoptim_end}
+ \label{fig:devol_return}
\end{sidewaysfigure}
@@ -1866,10 +1807,281 @@
\end{minipage}
\caption{\code{evaluate()} function versus Evaluation classes permitting
\proglang{R} and \proglang{C++} objective functions}
- \label{fig:deoptim_end}
+ \label{fig:evaluate_fun}
\end{sidewaysfigure}
+
+%% R functions
+
+\begin{sidewaysfigure} % fig R1: beginning of DEoptim()
+ \begin{minipage}{0.48\linewidth}
+ \tiny
+ \begin{CodeChunk}
+ \begin{CodeInput}
+DEoptim <- function(fn, lower, upper, control = DEoptim.control(), ...) {
+ fn1 <- function(par) fn(par, ...)
+ if (length(lower) != length(upper))
+ stop("'lower' and 'upper' are not of same length")
+ if (!is.vector(lower))
+ lower <- as.vector(lower)
+ if (!is.vector(upper))
+ upper <- as.vector(upper)
+ if (any(lower > upper))
+ stop("'lower' > 'upper'")
+ if (any(lower == "Inf"))
+ warning("you set a component of 'lower' to 'Inf'. May imply 'NaN' results", immediate. = TRUE)
+ if (any(lower == "-Inf"))
+ warning("you set a component of 'lower' to '-Inf'. May imply 'NaN' results", immediate. = TRUE)
+ if (any(upper == "Inf"))
+ warning("you set a component of 'upper' to 'Inf'. May imply 'NaN' results", immediate. = TRUE)
+ if (any(upper == "-Inf"))
+ warning("you set a component of 'upper' to '-Inf'. May imply 'NaN' results", immediate. = TRUE)
+ if (!is.null(names(lower)))
+ nam <- names(lower)
+ else if (!is.null(names(upper)) & is.null(names(lower)))
+ nam <- names(upper)
+ else
+ nam <- paste("par", 1:length(lower), sep = "")
+
+ ctrl <- do.call(DEoptim.control, as.list(control))
+ ctrl$npar <- length(lower)
+ if (ctrl$NP < 4) {
+ warning("'NP' < 4; set to default value 50\n", immediate. = TRUE)
+ ctrl$NP <- 50
+ }
+ if (ctrl$NP < 10*length(lower))
+ warning("For many problems it is best to set 'NP' (in 'control') to be at least "
+ "ten times the length of the parameter vector. \n", immediate. = TRUE)
+ if (!is.null(ctrl$initialpop)) {
+ ctrl$specinitialpop <- TRUE
+ if(!identical(as.numeric(dim(ctrl$initialpop)), c(ctrl$NP, ctrl$npar)))
+ stop("Initial population is not a matrix with dim. NP x length(upper).")
+ }
+ else {
+ ctrl$specinitialpop <- FALSE
+ ctrl$initialpop <- 0.0
+ }
+ ##
+ ctrl$trace <- as.numeric(ctrl$trace)
+ ctrl$specinitialpop <- as.numeric(ctrl$specinitialpop)
+ ctrl$initialpop <- as.numeric(ctrl$initialpop)
+ \end{CodeInput}
+ \end{CodeChunk}
+
+ \normalsize
+ \centering{Panel A: \proglang{R} version in \pkg{DEoptim}}
+ \tiny
+
+ \end{minipage}
+ \begin{minipage}{0.03\linewidth}
+ \phantom{XX}
+ \end{minipage}
+ \begin{minipage}{0.48\linewidth}
+ \tiny
+
+ \begin{CodeChunk}
+ \begin{CodeInput}
+DEoptim <- function(fn, lower, upper, control = DEoptim.control(), env, ...) {
+ ##fn1 <- function(par) fn(par, ...)
+ if (length(lower) != length(upper))
+ stop("'lower' and 'upper' are not of same length")
+ if (!is.vector(lower))
+ lower <- as.vector(lower)
+ if (!is.vector(upper))
+ upper <- as.vector(upper)
+ if (any(lower > upper))
+ stop("'lower' > 'upper'")
+ if (any(lower == "Inf"))
+ warning("you set a component of 'lower' to 'Inf'. May imply 'NaN' results", immediate. = TRUE)
+ if (any(lower == "-Inf"))
+ warning("you set a component of 'lower' to '-Inf'. May imply 'NaN' results", immediate. = TRUE)
+ if (any(upper == "Inf"))
+ warning("you set a component of 'upper' to 'Inf'. May imply 'NaN' results", immediate. = TRUE)
+ if (any(upper == "-Inf"))
+ warning("you set a component of 'upper' to '-Inf'. May imply 'NaN' results", immediate. = TRUE)
+ if (!is.null(names(lower)))
+ nam <- names(lower)
+ else if (!is.null(names(upper)) & is.null(names(lower)))
+ nam <- names(upper)
+ else
+ nam <- paste("par", 1:length(lower), sep = "")
+ if (missing(env))
+ env <- new.env()
+
+ ctrl <- do.call(DEoptim.control, as.list(control))
+ ctrl$npar <- length(lower)
+ if (ctrl$NP < 4) {
+ warning("'NP' < 4; set to default value 50\n", immediate. = TRUE)
+ ctrl$NP <- 50
+ }
+ if (ctrl$NP < 10*length(lower))
+ warning("For many problems it is best to set 'NP' (in 'control') to be at least ten"
+ " times the length of the parameter vector. \n", immediate. = TRUE)
+ if (!is.null(ctrl$initialpop)) {
+ ctrl$specinitialpop <- TRUE
+ if(!identical(as.numeric(dim(ctrl$initialpop)), c(ctrl$NP, ctrl$npar)))
+ stop("Initial population is not a matrix with dim. NP x length(upper).")
+ }
+ else {
+ ctrl$specinitialpop <- FALSE
+ ctrl$initialpop <- matrix(0,1,1) # dummy matrix
+ }
+ ##
+ ctrl$trace <- as.numeric(ctrl$trace)
+ ctrl$specinitialpop <- as.numeric(ctrl$specinitialpop)
+ \end{CodeInput}
+ \end{CodeChunk}
+
+ \normalsize
+ \centering{Panel B: \proglang{R} version in \pkg{RcppDE}}
+ \end{minipage}
+ \caption{First half of \proglang{R} function \texttt{DEoptim()}}
+ \label{fig:fig_R_DEoptim1}
+\end{sidewaysfigure}
+
[TRUNCATED]
To get the complete diff run:
svnlook diff /svnroot/rcpp -r 2730
More information about the Rcpp-commits
mailing list