1\documentclass[dakotalogo]{dakota-article}
2
3
4\usepackage{pifont}% allow use of arrows for items
5\newcommand{\myitem}{\item[\color{darkblue}\ding{228}]}
6
7
8\funding{This work was supported by ASC software. Sandia National Laboratories is a multi-program laboratory managed and operated by Sandia Corporation, a wholly
9owned subsidiary of Lockheed Martin Corporation, for the U.S. Department of Energy's National Nuclear Security
10Administration under contract DE-AC04-94AL85000.}
11\def\mytitle{Surrogates: Emulating computer simulations}
12\title{\mytitle}
13\shorttitle{Dakota Technical Design Document}
14\date{March 2017}
15\def\mycorauthor{John D. Jakeman}
16\corauthor{\mycorauthor}
17\coremail{jdjakem@sandia.gov}
18
19\def\SNL{Sandia National Laboratories, Albuquerque, New Mexico, USA }
20%\def\corauthor{{\color{darkblue} Correspondence author}. \SNL   (jdjakem@sandia.gov)}
21
22\shortauthor{Adams, Hooper, Jakeman, Rushdi}
23\author{B. Adams\thanks{\SNL}, R. Hooper\samethanks[1], \mycorauthor\samethanks[1], A. Rushdi\samethanks[1]}
24
25\setlength{\headheight}{21pt}%
26\begin{document}
27\pagestyle{myheader}
28\maketitle
29\section{Introduction}
30\subsection{Purpose}
31This library will provide a suite of algorithms for emulating expensive computer simulations.
32
33\subsection{Scope}
34This library will replace the existing surrogate tools in Dakota and enrich these existing tools with additional state of the art surrogates and algorithms.
35
36\subsection{Overview}
37This library will consist of 5 main software components visible to the user at the highest level of abstraction:
38\begin{itemize}
39\myitem Function - A class, from which surrogates is derived whose interface represents the mathematical properties of a $C_2$ continous function, e.g supports evaluation of values, gradients and Hessians. evaluated
40\myitem Variables - A class defining the properties of the function variables, e.g. probability distribution, ranges, etc. We will support all current Dakota Variable types in addition to blocks of correlated variables whose distribution is known, data-based-variables whose distribution is computed from data, and compositions of all variables.
41\myitem Data - A class to store data returned by function and the associated samples of the function variables. This class will also contain fault information. We must provide modules that convert simple structures such as matrices and vectors of samples and values into this class.
42\myitem SurrogateFactory - A factory to construct a surrogate/approximation. Typical workflow will be generate a set of samples, evaluate function at those samples and build approximation. This call structure can be repeated iteratively to build up surrogates adaptively. We will also support the use and enrichment of archived data. This factor will support typical Dakota use-cases, however uses will be easily able to develop and add there own methods for building surrogates.
43\myitem SurrogateAnalyzer - A factory for running various types of analysis on surrogate models, e.g. compute moments, sobol indices, etc. If certain surrogates support fast operations to compute these values, e.g. PCE can compute mean and variance analytically these specialized functions will be envoked, but other wise a default will be called.
44\end{itemize}
45Currently the above notions of function and surrogate builders and analysis are heaverly intertwined in Dakota. Our design will allow these distinct components to be separated. This will allow surrogates to become a standalone part of the dakota Model hierarchy and surrogate analyzers to become lightweight Dakota Iterators.
46
47\subsection{Requirements}
48The following is a list of requirements
49\begin{itemize}
50\myitem User flexibity. Design must support 'push-button' users that want hired wired behavior and power users that wish to develop their own surrogate methods or expose low-level functionality.
51\myitem Serialization of surrogates - Ability to save and load surrogate objects
52\myitem Python interface - be able to call both high-level and low-level functions using Python.
53\myitem Gaussian Process consolidation - Consolidate GP methods in Dakota. Extend GP to include estimation of hyper-parametersa and use PCE trend function.
54\myitem Surrogates for multiple QOI - Build a single surrogate for multiple QOI. Allow for composition of surrogate types.
55\myitem Exending variable class - Support all Dakota variable types as well as blocks of correlated variables whose distribution is known, data-based-variables whose distribution is computed from data, and compositions of all variables. Retirement of AleatoryDistParams in Dakota.
56\myitem Simple approximation classes. Separation of approximation and the code used to construct it. Particularly relevant in Pecos. RegressOrthogPolynomial contains PCE object but also regression methods used to build the PCE. Similarly for Sparse grids need to seperate approximation, either lagrange polynomials or PCE, from refinement tools For example, split current subspaces which are part of approximation from active subspaces being considered for refinement which should only been known to sparse grid builder
57\myitem Function Data. The function data class should have no notion of active and stored data we shold just use indexing to access the data needed.
58\end{itemize}
59
60
61\section{Design}
62\subsection{High-level interface}
63The following is an example of the typical workflow used to build a surrogate
64\begin{codelisting}[]{Construct Surrogate Demonstration}
65
66// Configure options used to build surrogate
67Teuchos::ParameterList factor_opts;
68factory_opts.set(function, "target function");
69factory_opts.set(data, "optional archived data");
70factory_opts.set(PCE, "approximation type");
71factory_opts.set("regression", "construction method");
72//factory_opts.set("adapted-regression", "construction method");
73factory_opts.set("OMP", "regression solver");
74factory_opts.set("random", "sample type");
75//factory_opts.set("optimal", "sample type");
76
77// Build surrogate
78Teuchos::RCP<Approximation> approx = SurrogateFactory(factory_opts);
79
80// Analyze surrogate
81Teuchos::ParameterList analyzer_opts;
82analyzer_opts.set(MOMENTS, "analysis type");
83Teuchos::RCP<AnalyzerMetrics> result = SurrogateAnalyzer(approx, analyzer_opts);
84
85// Print metrics
86std::cout << "Mean: " << result.get("mean") << std::endl;
87std::cout << "Variance: " << result.get("variance") << std::endl;
88
89\end{codelisting}
90
91\subsection{Surrogate Interface}
92We will use a factory pattern to build a surrogate. The Surrogate factory will call lower level factories which are specific to each type of approximation. Approximation types can be added at these levels without the call to surrogate factory being modified. These new types can just be created by passing appropriate options via {\texttt Teuchos::ParameterList}.
93\begin{codelisting}[]{Surrogate Factory}
94enum ApproxType {PCE,GP};
95Teuchos::RCP<Approximation> surrogate_factory(const Teuchos::ParameterList opts){
96  ApproxType approx_type = opts.get<ApproxType>("approximation type");
97  switch (approx_type){
98    case PCE : {
99      return PCEFactory(opts, approx);
100    }
101    case GP : {
102      return GPFactory(opts, approx);
103    }
104    default : {
105      throw(std::runtime_error("Incorrect approximation type"));
106    }
107  }
108}
109\end{codelisting}
110
111\subsection{Surrogate Analyzer}
112The surrogate analyzer will be implemented using a factory pattern. The analyzer will support various types of analysis on surrogate models, e.g. the computation of moments, sobol indices, etc. If certain surrogates support fast operations to compute these values, e.g. PCE can compute mean and variance analytically these specialized functions will be envoked, but other wise a default will be called.
113\begin{codelisting}{Surrogate Analyzer}
114enum AnalysisType {MOMENTS,SOBOL_INDICES};
115Teuchos::RCP<AnaylzerMetrics> surrogate_anaylzer_factory(const Teuchos::ParameterList opts, Approximation &approx){
116  AnalysisType analysis_type = opts.get<AnalysisType>("analysis type");
117  switch (analysis_type){
118    case MOMENTS : {
119      RealVector means, variances;
120      Teuchos::ParameterList moment_opts;
121      moment_opts.set(false, "compute mean");
122      moment_opts.set(false, "compute variance");
123      if (!approx.get("mean",means))
124      // if specialized method does not exist use default
125      moment_opts.set(true, "compute mean");
126      if (!approx.get("variance",variances))
127      // if specialized method does not exist use default
128      moment_opts.set(true, "compute variance");
129      compute_moments_using_sampling_carlo(
130      approx,moment_opts,means,variances)
131      break;
132    }
133    case SOBOL_INDICES : {
134      RealMatrix sobol_indices;
135      if (!approx.get("sobol_indices",sobol_indices))
136      // if specialized method does not exist use default
137      // opts can contain options like restricted indices
138      compute_sobol_indices_using_sampling(approx,opts,sobol_indices);
139      break;
140    }
141    default : {
142      throw(std::runtime_error("Incorrect approximation type"));
143    }
144  }
145}
146\end{codelisting}
147
148\subsection{Approximations}
149Approximations will all be derived from a base function class. The interface of the function class will be restricted to only those functions that represents the mathematical properties of a $C_2$ continous function, e.g supports evaluation of values, gradients and Hessians. Each approximation will only contain the methods relevant to its construction, e.g. PCE has {\texttt build\_basis\_matrix} and {\texttt set\_coefficients} and GP has {\texttt build\_correlation\_matrix} and {\texttt set\_correlation\_lenghts}.
150
151The basic approximation class hierarchy is depicted in Figure~\ref{fig:approx-class-hierarcy}. This hierarchy will be extended as additional approximation types are added.
152
153\begin{figure}[htb]\centering
154\includegraphics[width=0.7\textwidth]{classSurrogates_1_1Function.png}
155\caption{Function class hierarchy.}
156\label{fig:approx-class-hierarcy}
157\end{figure}
158
159\subsubsection{Function base class}
160
161Here we describe the abstract base class representation of a function $f(x)$ for a multivariate variable x.
162Functions derived from this class can either be $C_0, C_1$ or $C_2$
163 continuous. Regardlesd of the function regularity any derived class must
164implement value(), $C_1$ functions must implement gradient() and jacobian()
165and $C_2$ functions must implement hessian().
166
167To avoid complexity of the function hierarchy we do not create seperate classes
168for  $C_0, C_1$ and $C_2$ functions but rather only implement the
169functions necessitated by the function regularity. All other functions must
170raise an exception if called (these exceptions are implemented in this base
171class)
172\begin{figure}[htb]\centering
173\includegraphics[width=0.7\textwidth]{function-class-members.png}
174\caption{Function base class member functions.}
175\end{figure}
176
177QUESTION: Do we have functions for value, gradient, hessian or do we
178have a function value(samples,opts) where opts specifies what of the
179three data to return.
180
181\subsection{Variables}
182Variables is a class defining the properties of the function variables, e.g. probability distribution, ranges, etc. There is almost no functionality in the base class except {\texttt num\_vars}. The rest of the functionality is implemented in the derived class and variable transformations or approximations which use the derived class must know what additional functions are implemented. An example of a variable class is shown in Figure~\ref{fig:bounded-vars-class}.
183
184\begin{figure}[htb]\centering
185\includegraphics[width=0.7\textwidth]{bounded-vars-members.png}
186\caption{Example of a variables class.}
187\label{fig:bounded-vars-class}
188\end{figure}
189
190\subsubsection{Variable Transformations}
191Surrogates will sometimes the users provided variables to be mapped to a set of variables that the approximation can use. E.g a PCE requires variables on canonical domains such as Uniform on $[-1,1]$. These mappings are peformed by variable transformations. An example implementation for an affine transformation of bounded variables is shown below.
192\begin{codelisting}{Example of variable transformation code}
193void AffineVariableTransformation::
194map_samples_from_user_space(const RealMatrix &samples,
195RealMatrix &transformed_samples) const {
196  int num_vars = boundedVars_->num_vars();
197  if ( samples.numRows() != boundedVars_->num_vars() )
198    throw( std::runtime_error("Samples have incorrect number of random variables") );
199
200  int num_samples = samples.numCols();
201  transformed_samples.shapeUninitialized(num_vars, num_samples);
202  for ( int j=0; j<num_samples; j++ ){
203    for ( int i=0; i<num_vars; i++ ){
204      transformed_samples(j,i) =
205	(samples(i,j)+1)/2.*(boundedVars_->ub(i)-boundedVars_->lb(i))+boundedVars_->lb(i);
206    }
207  }
208}
209\end{codelisting}
210
211Here is an example of using a variable transformation
212\section{Approximation Builders}
213The approximation factories call approximation builders. An example of
214how a builder may work is given below. This builder consists of two
215steps defining the approximation and the sampling the function and
216solving for its coefficients using regression. builders may call
217other builder in an inner loop. For example we may wish to iteratively
218add samples. In which case we would call this builder in an inner loop
219until an error estimate reaches a desired level of accuracy. In the
220example below we pass in a function but we could also pass in existing data.
221\begin{codelisting}{Example of a surrogate builder}
222// Define the function variables
223  RealVector ranges;
224  define_homogeneous_ranges(num_vars, 0., 1., ranges);
225  Teuchos::RCP<Variables> variables(new BoundedVariables());
226  Teuchos::rcp_dynamic_cast<BoundedVariables>(variables)->set_ranges(ranges);
227
228  // Define the variable transformation. Need to decide if a seperate
229  // transformation should exist for approximation and for mapping samples
230  // generated. For example approximation accepts samples in user x-space
231  // but operates in a standardized u-space. But sample generator produces
232  // samples in (possibly another standardized space) and must map these to
233  // x-space, or even to approximation u-space.
234  Teuchos::RCP<VariableTransformation> var_transform(new AffineVariableTransformation());
235  var_transform->set_variables(variables);
236
237// Initialize the approximation
238  Teuchos::ParameterList monomial_opts;
239  monomial_opts.set("max_total_degree",degree,
240		    "max degree of total-degree polynomial space");
241  monomial_opts.set("num_qoi", num_qoi, "number of quantites of interest.");
242  Monomial monomial;
243  monomial.set_options(monomial_opts);
244  monomial.set_variable_transformation(var_transform);
245  IntMatrix basis_indices;
246  compute_hyperbolic_indices(num_vars, degree, 1., basis_indices);
247  monomial.set_basis_indices(basis_indices);
248
249  // Generate the approximation coefficients using a regression based method
250  Teuchos::ParameterList regression_opts;
251  regression_opts.set("regression type",SVD_LEAST_SQ_REGRESSION);
252  regression_opts.set("num_samples",num_samples);
253  regression_opts.set("sample_type","probabilistic_MC");
254  RegressionBuilder builder;
255  builder.set_target_function(model);
256  builder.build(regression_opts, monomial);
257\end{codelisting}
258QUESTION: DO we pass in target function and any data through
259ParameterList opts or through member functions?
260\subsection{Regression methods}
261For a given approximation type, there are a number of ways one might want
262to construt the approximation. For example we can use different types
263of regression to build a PCE, neural net etc, or we may want to build
264a pseudo spectral pce using different types of quadrature. In these
265cases we need factories to choose the builder sub-component,
266e.g. least squares or l1 minimization for regression based pce, or
267monte carlo or sparse grid quadrature for pseudo spectral pce.
268An example of such builders is given below.
269\begin{codelisting}[]{Example builder for regression based
270    approximations}
271  // Generate samples to build approximation
272  int num_samples = opts.get<int>("num_samples");
273  std::string sample_type = opts.get<std::string>("sample_type");
274
275  // Create mc sampler and pass in sample type.
276  // For now hack support for uniform mc sampler
277  RealMatrix samples;
278  int seed = 1337;
279  Teuchos::RCP<VariableTransformation> var_transform =
280    approx.get_variable_transformation();
281  generate_uniform_samples(approx.num_vars(), num_samples, seed,
282			   *var_transform, samples);
283
284  // Evaluate the function at the build samples
285  RealMatrix values;
286  targetFunction_->value(samples, values);
287
288  //\todo consider having opts have multiple parameterLists
289  //each associated with a particular aspect of build
290  //e.g. opts = (sample_opts, regression_opts)
291  PolynomialApproximation& poly_approx =
292    dynamic_cast<PolynomialApproximation&>(approx);
293
294  // Generate matrix of the linear system to be used in
295  // regression solve
296  RealMatrix basis_matrix;
297  poly_approx.generate_basis_matrix(samples,basis_matrix);
298
299  // Solve regression problem to get coefficients
300  Teuchos::RCP<LinearSystemSolver> solver =
301    regression_solver_factory(opts);
302  RealMatrix coeffs, metrics;
303  solver->solve(basis_matrix, values, coeffs, metrics, opts);
304
305  // Set the approximation coefficients
306  poly_approx.set_coefficients(coeffs);
307\end{codelisting}
308The solvers inheritance diagram is depicted in
309Figure~\ref{fig:regresion-solver-inheritance}. The hierarchy lets each
310class define specialized implementations of things like cross
311validation. Sparse solvers have a default implementation of iterative
312reweighting which they can call, the definition of this function DOES
313NOT exist in the base class.
314\begin{figure}[htb]\centering
315\includegraphics[width=0.7\textwidth]{classSurrogates_1_1LinearSystemSolver.png}
316\caption{The regression solver hierarchy.}
317\label{fig:regresion-solver-inheritance}
318\end{figure}
319Specialization of sparse solver is shown in
320Figure~\ref{fig:sparse-solver-members}
321\begin{figure}[htb]\centering
322\includegraphics[width=0.7\textwidth]{sparsesolverclass.jpeg}
323\caption{Sparse solver member functions. Only solve exists in baseclass}
324\label{fig:sparse-solver-members}
325\end{figure}
326\section{Integration with Dakota}
327Currently the notions of Approximation (DataFitSurrogate) and surrogate builders and analysis are heaverly intertwined in Dakota. Our design will allow these distinct components to be separated. This will allow Approximation to become a standalone part of the dakota Model hierarchy and surrogate analyzers to become lightweight Dakota Iterators.
328
329\include{variables_class}
330
331% \begin{figure}[htb]\centering
332% %\includegraphics[width=0.7\textwidth]{bounded-vars-members.png}
333% \caption{The relationship of surrogate classes to the Dakota class hierarchy}
334% \label{fig:bounded-vars-class}
335% \end{figure}
336\end{document}
337
338%%% Local Variables:
339%%% mode: latex
340%%% TeX-master: t
341%%% End:
342