ROL
ROL_SROMGenerator.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Rapid Optimization Library (ROL) Package
4 //
5 // Copyright 2014 NTESS and the ROL contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef ROL_SROMGENERATOR_HPP
11 #define ROL_SROMGENERATOR_HPP
12 
15 #include "ROL_SampleGenerator.hpp"
16 #include "ROL_MomentObjective.hpp"
17 #include "ROL_CDFObjective.hpp"
19 #include "ROL_SROMVector.hpp"
20 #include "ROL_StdVector.hpp"
21 #include "ROL_SingletonVector.hpp"
22 #include "ROL_Bounds.hpp"
23 
24 namespace ROL {
25 
26 template<class Real>
27 class SROMGenerator : public SampleGenerator<Real> {
28 private:
29  // Parameterlist for optimization
30  ROL::ParameterList parlist_;
31  // Vector of distributions (size = dimension of space)
32  std::vector<Ptr<Distribution<Real>>> dist_;
33 
34  const int dimension_;
38  bool adaptive_;
39 
40  Real ptol_;
41  Real atol_;
42 
44  const AtomVector<Real> &atom) {
45  // Remove points with zero weight
46  std::vector<std::vector<Real>> pts;
47  std::vector<Real> wts;
48  for (int i = 0; i < numMySamples_; i++) {
49  if ( prob.getProbability(i) > ptol_ ) {
50  pts.push_back(*(atom.getAtom(i)));
51  wts.push_back(prob.getProbability(i));
52  }
53  }
54  numMySamples_ = wts.size();
55  // Remove atoms that are within atol of each other
56  Real err = 0.0;
57  std::vector<Real> pt;
58  std::vector<int> ind;
59  for (int i = 0; i < numMySamples_; i++) {
60  pt = pts[i]; ind.clear();
61  for (int j = i+1; j < numMySamples_; j++) {
62  err = 0.0;
63  for (int d = 0; d < dimension_; d++) {
64  err += std::pow(pt[d] - pts[j][d],2);
65  }
66  err = std::sqrt(err);
67  if ( err < atol_ ) {
68  ind.push_back(j);
69  for (int d = 0; d < dimension_; d++) {
70  pts[i][d] += pts[j][d];
71  wts[i] += wts[j];
72  }
73  }
74  }
75  if ( ind.size() > 0 ) {
76  for (int d = 0; d < dimension_; d++) {
77  pts[i][d] /= (Real)(ind.size()+1);
78  }
79  for (int k = ind.size()-1; k >= 0; k--) {
80  pts.erase(pts.begin()+ind[k]);
81  wts.erase(wts.begin()+ind[k]);
82  }
83  }
84  numMySamples_ = wts.size();
85  }
86  // Renormalize weights
87  Real psum = 0.0, sum = 0.0;
88  for (int i = 0; i < numMySamples_; i++) {
89  psum += wts[i];
90  }
91  SampleGenerator<Real>::sumAll(&psum,&sum,1);
92  for (int i = 0; i < numMySamples_; i++) {
93  wts[i] /= sum;
94  }
95  // Set points and weights
98  }
99 
100 public:
101 
102  SROMGenerator(ROL::ParameterList &parlist,
103  const Ptr<BatchManager<Real>> &bman,
104  const std::vector<Ptr<Distribution<Real>>> &dist,
105  std::ostream &outStream = std::cout)
106  : SampleGenerator<Real>(bman), parlist_(parlist), dist_(dist),
107  dimension_(dist.size()) {
108  // Get SROM sublist
109  ROL::ParameterList &list = parlist.sublist("SOL").sublist("Sample Generator").sublist("SROM");
110  numSamples_ = list.get("Number of Samples",50);
111  adaptive_ = list.get("Adaptive Sampling",false);
112  numNewSamples_ = list.get("Number of New Samples Per Adaptation",0);
113  ptol_ = list.get("Probability Tolerance",1.e2*std::sqrt(ROL_EPSILON<Real>()));
114  atol_ = list.get("Atom Tolerance",1.e2*std::sqrt(ROL_EPSILON<Real>()));
115  bool presolve = list.get("Presolve for Atom Locations",false);
116  // Compute batch local number of samples
117  int rank = (int)SampleGenerator<Real>::batchID();
118  int nProc = (int)SampleGenerator<Real>::numBatches();
119  int frac = numSamples_ / nProc;
120  int rem = numSamples_ % nProc;
121  numMySamples_ = frac + ((rank < rem) ? 1 : 0);
122  // Initialize vectors
123  Ptr<ProbabilityVector<Real>> prob, prob_lo, prob_hi, prob_eq;
124  Ptr<AtomVector<Real>> atom, atom_lo, atom_hi, atom_eq;
125  Ptr<Vector<Real>> x, x_lo, x_hi, x_eq;
126  initialize_vectors(prob,prob_lo,prob_hi,prob_eq,atom,atom_lo,atom_hi,atom_eq,x,x_lo,x_hi,x_eq,bman);
127  Ptr<Vector<Real>> l = makePtr<SingletonVector<Real>>(0.0);
128  // Initialize constraints
129  Ptr<BoundConstraint<Real>> bnd = makePtr<Bounds<Real>>(x_lo,x_hi);
130  Ptr<Constraint<Real>> con = makePtr<ScalarLinearConstraint<Real>>(x_eq,1.0);
131  if (presolve) { // Optimize over atom locations only
132  ROL::ParameterList pslist(list);
133  pslist.sublist("Step").set("Type","Trust Region");
134  Ptr<Objective<Real>> obj = initialize_objective(dist,bman,false,true,pslist);
135  OptimizationProblem<Real> optProblem(obj,x,bnd);
136  OptimizationSolver<Real> optSolver(optProblem, pslist);
137  optSolver.solve(outStream);
138  }
139  // Optimization over atom locations and probabilities
140  Ptr<Objective<Real>> obj = initialize_objective(dist,bman,true,true,list);
141  OptimizationProblem<Real> optProblem(obj,x,bnd,con,l);
142  optProblem.check(outStream);
143  OptimizationSolver<Real> optSolver(optProblem, list);
144  optSolver.solve(outStream);
145  // Prune samples with zero weight and set samples/weights
146  pruneSamples(*prob,*atom);
147  }
148 
149  void refine(void) {}
150 
151 private:
152 
153  void get_scaling_vectors(std::vector<Real> &typw, std::vector<Real> &typx) const {
154  typw.clear(); typx.clear();
155  typw.resize(numMySamples_,(Real)(numSamples_*numSamples_));
156  typx.resize(numMySamples_*dimension_,0);
157  Real mean = 1, var = 1, one(1);
158  for (int j = 0; j < dimension_; j++) {
159  mean = std::abs(dist_[j]->moment(1));
160  var = dist_[j]->moment(2) - mean*mean;
161  mean = ((mean > ROL_EPSILON<Real>()) ? mean : std::sqrt(var));
162  mean = ((mean > ROL_EPSILON<Real>()) ? mean : one);
163  for (int i = 0; i < numMySamples_; i++) {
164  typx[i*dimension_ + j] = one/(mean*mean);
165  }
166  }
167  }
168 
170  Ptr<ProbabilityVector<Real>> &prob_lo,
171  Ptr<ProbabilityVector<Real>> &prob_hi,
172  Ptr<ProbabilityVector<Real>> &prob_eq,
173  Ptr<AtomVector<Real>> &atom,
174  Ptr<AtomVector<Real>> &atom_lo,
175  Ptr<AtomVector<Real>> &atom_hi,
176  Ptr<AtomVector<Real>> &atom_eq,
177  Ptr<Vector<Real>> &vec,
178  Ptr<Vector<Real>> &vec_lo,
179  Ptr<Vector<Real>> &vec_hi,
180  Ptr<Vector<Real>> &vec_eq,
181  const Ptr<BatchManager<Real>> &bman) const {
182  // Compute scaling for probability and atom vectors
183  std::vector<Real> typx, typw;
184  get_scaling_vectors(typw,typx);
185  // Compute initial guess and bounds for probability and atom vectors
186  std::vector<Real> pt(dimension_*numMySamples_,0.), wt(numMySamples_,1./(Real)numSamples_);
187  std::vector<Real> pt_lo(dimension_*numMySamples_,0.), pt_hi(dimension_*numMySamples_,0.);
188  std::vector<Real> wt_lo(numMySamples_,0.), wt_hi(numMySamples_,1.);
189  std::vector<Real> pt_eq(dimension_*numMySamples_,0.), wt_eq(numMySamples_,1.);
190  Real lo = 0., hi = 0.;
191  srand(12345*SampleGenerator<Real>::batchID());
192  for ( int j = 0; j < dimension_; j++) {
193  lo = dist_[j]->lowerBound();
194  hi = dist_[j]->upperBound();
195  for (int i = 0; i < numMySamples_; i++) {
196  pt[i*dimension_ + j] = dist_[j]->invertCDF((Real)rand()/(Real)RAND_MAX);
197  //pt[i*dimension_ + j] = dist_[j]->invertCDF(0);
198  pt_lo[i*dimension_ + j] = lo;
199  pt_hi[i*dimension_ + j] = hi;
200  }
201  }
202  // Build probability, atom, and SROM vectors
203  prob = makePtr<PrimalProbabilityVector<Real>>(
204  makePtr<std::vector<Real>>(wt),bman,
205  makePtr<std::vector<Real>>(typw));
206  atom = makePtr<PrimalAtomVector<Real>>(
207  makePtr<std::vector<Real>>(pt),bman,numMySamples_,dimension_,
208  makePtr<std::vector<Real>>(typx));
209  vec = makePtr<SROMVector<Real>>(prob,atom);
210  // Lower and upper bounds on Probability Vector
211  prob_lo = makePtr<PrimalProbabilityVector<Real>>(
212  makePtr<std::vector<Real>>(wt_lo),bman,
213  makePtr<std::vector<Real>>(typw));
214  prob_hi = makePtr<PrimalProbabilityVector<Real>>(
215  makePtr<std::vector<Real>>(wt_hi),bman,
216  makePtr<std::vector<Real>>(typw));
217  // Lower and upper bounds on Atom Vector
218  atom_lo = makePtr<PrimalAtomVector<Real>>(
219  makePtr<std::vector<Real>>(pt_lo),bman,numMySamples_,dimension_,
220  makePtr<std::vector<Real>>(typx));
221  atom_hi = makePtr<PrimalAtomVector<Real>>(
222  makePtr<std::vector<Real>>(pt_hi),bman,numMySamples_,dimension_,
223  makePtr<std::vector<Real>>(typx));
224  // Lower and upper bounds on SROM Vector
225  vec_lo = makePtr<SROMVector<Real>>(prob_lo,atom_lo);
226  vec_hi = makePtr<SROMVector<Real>>(prob_hi,atom_hi);
227  // Constraint vectors
228  prob_eq = makePtr<DualProbabilityVector<Real>>(
229  makePtr<std::vector<Real>>(wt_eq),bman,
230  makePtr<std::vector<Real>>(typw));
231  atom_eq = makePtr<DualAtomVector<Real>>(
232  makePtr<std::vector<Real>>(pt_eq),bman,numMySamples_,dimension_,
233  makePtr<std::vector<Real>>(typx));
234  vec_eq = makePtr<SROMVector<Real>>(prob_eq,atom_eq);
235  }
236 
237  Ptr<Objective<Real>> initialize_objective(const std::vector<Ptr<Distribution<Real>>> &dist,
238  const Ptr<BatchManager<Real>> &bman,
239  const bool optProb, const bool optAtom,
240  ROL::ParameterList &list) const {
241  std::vector<Ptr<Objective<Real>>> obj_vec;
242  // Build CDF objective function
243  Real scale = list.get("CDF Smoothing Parameter",1.e-2);
244  obj_vec.push_back(makePtr<CDFObjective<Real>>(dist,bman,scale,optProb,optAtom));
245  // Build moment matching objective function
246  std::vector<int> tmp_order
247  = ROL::getArrayFromStringParameter<int>(list,"Moments");
248  std::vector<int> order(tmp_order.size(),0);
249  for (unsigned int i = 0; i < tmp_order.size(); i++) {
250  order[i] = static_cast<int>(tmp_order[i]);
251  }
252  obj_vec.push_back(makePtr<MomentObjective<Real>>(dist,order,bman,optProb,optAtom));
253  // Build linear combination objective function
254  std::vector<Real> tmp_coeff
255  = ROL::getArrayFromStringParameter<Real>(list,"Coefficients");
256  std::vector<Real> coeff(2,0.);
257  coeff[0] = tmp_coeff[0]; coeff[1] = tmp_coeff[1];
258  return makePtr<LinearCombinationObjective<Real>>(coeff,obj_vec);
259  }
260 
261  int numGlobalSamples(void) const {
262  return numSamples_;
263  }
264 };
265 
266 }
267 
268 #endif
Provides the std::vector implementation of the ROL::Vector interface.
const Real getProbability(const int i) const
ROL::Ptr< const std::vector< Real > > getAtom(const int i) const
int numGlobalSamples(void) const
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
void initialize_vectors(Ptr< ProbabilityVector< Real >> &prob, Ptr< ProbabilityVector< Real >> &prob_lo, Ptr< ProbabilityVector< Real >> &prob_hi, Ptr< ProbabilityVector< Real >> &prob_eq, Ptr< AtomVector< Real >> &atom, Ptr< AtomVector< Real >> &atom_lo, Ptr< AtomVector< Real >> &atom_hi, Ptr< AtomVector< Real >> &atom_eq, Ptr< Vector< Real >> &vec, Ptr< Vector< Real >> &vec_lo, Ptr< Vector< Real >> &vec_hi, Ptr< Vector< Real >> &vec_eq, const Ptr< BatchManager< Real >> &bman) const
void sumAll(Real *input, Real *output, int dim) const
SROMGenerator(ROL::ParameterList &parlist, const Ptr< BatchManager< Real >> &bman, const std::vector< Ptr< Distribution< Real >>> &dist, std::ostream &outStream=std::cout)
ROL::ParameterList parlist_
void get_scaling_vectors(std::vector< Real > &typw, std::vector< Real > &typx) const
Provides the std::vector implementation of the ROL::Vector interface.
Provides a simplified interface for solving a wide range of optimization problems.
std::vector< Ptr< Distribution< Real > > > dist_
Ptr< Objective< Real > > initialize_objective(const std::vector< Ptr< Distribution< Real >>> &dist, const Ptr< BatchManager< Real >> &bman, const bool optProb, const bool optAtom, ROL::ParameterList &list) const
void check(std::ostream &outStream=std::cout, const int numSteps=ROL_NUM_CHECKDERIV_STEPS, const int order=1)
void setPoints(std::vector< std::vector< Real > > &p)
int solve(const ROL::Ptr< StatusTest< Real > > &status=ROL::nullPtr, const bool combineStatus=true)
Solve optimization problem with no iteration output.
void setWeights(std::vector< Real > &w)
void pruneSamples(const ProbabilityVector< Real > &prob, const AtomVector< Real > &atom)