1 // @HEADER
2 // ************************************************************************
3 //
4 //               Rapid Optimization Library (ROL) Package
5 //                 Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 //              Drew Kouri   (dpkouri@sandia.gov) and
39 //              Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 #ifndef ROL_PDEOPT_BRANCHING_PEBBL_H
45 #define ROL_PDEOPT_BRANCHING_PEBBL_H
46 
47 #include "ROL_PEBBL_Interface.hpp"
48 
49 template<class Real>
50 class ADVDIFF_BranchSub;
51 
52 template<class Real>
53 class ADVDIFF_Branching : public ROL::ROL_PEBBL_Branching<Real> {
54 private:
55   const int method_;
56   ROL::Ptr<ROL::Vector<Real>> z0_;
57 
58   using ROL::ROL_PEBBL_Branching<Real>::verbosity_;
59   using ROL::ROL_PEBBL_Branching<Real>::outStream_;
60   using ROL::ROL_PEBBL_Branching<Real>::parlist_;
61 
62 public:
ADVDIFF_Branching(const ROL::Ptr<BinaryAdvDiffFactory<Real>> & factory,const ROL::Ptr<ROL::ParameterList> & parlist,const ROL::Ptr<ROL::BranchHelper_PEBBL<Real>> & bHelper,int verbosity=0,const ROL::Ptr<std::ostream> & outStream=ROL::nullPtr,int method=0)63   ADVDIFF_Branching(const ROL::Ptr<BinaryAdvDiffFactory<Real>>            &factory,
64                     const ROL::Ptr<ROL::ParameterList>                    &parlist,
65                     const ROL::Ptr<ROL::BranchHelper_PEBBL<Real>>         &bHelper,
66                     int                                                    verbosity = 0,
67                     const ROL::Ptr<std::ostream>                          &outStream = ROL::nullPtr,
68                     int                                                    method = 0)
69     : ROL::ROL_PEBBL_Branching<Real>::ROL_PEBBL_Branching(factory,parlist,bHelper,verbosity,outStream),
70       method_(method) {
71     z0_ = factory->buildSolutionVector();
72   }
73 
blankSub()74   pebbl::branchSub* blankSub() {
75     return new ADVDIFF_BranchSub<Real>(ROL::makePtrFromRef<ADVDIFF_Branching<Real>>(*this),verbosity_,outStream_,method_);
76   }
77 
78 //  pebbl::solution* iniitalGuess() {
79 //
80 //  }
81 }; // ADVDIFF_Branching
82 
83 template <class Real>
84 class ADVDIFF_BranchSub : public ROL::ROL_PEBBL_BranchSub<Real> {
85 private:
86   const int method_;
87   std::string methodName_;
88 
89   using ROL::ROL_PEBBL_BranchSub<Real>::branching_;
90   using ROL::ROL_PEBBL_BranchSub<Real>::problem0_;
91   using ROL::ROL_PEBBL_BranchSub<Real>::solution_;
92   using ROL::ROL_PEBBL_BranchSub<Real>::rndSolution_;
93   using ROL::ROL_PEBBL_BranchSub<Real>::verbosity_;
94   using ROL::ROL_PEBBL_BranchSub<Real>::outStream_;
95 
round(ROL::Vector<Real> & rx,const ROL::Vector<Real> & x,Real t) const96   void round(ROL::Vector<Real> &rx, const ROL::Vector<Real> &x, Real t) const {
97     rx.set(x);
98     ROL::Ptr<std::vector<Real>> data = getParameter(rx);
99     Real val(0);
100     for (auto it = data->begin(); it != data->end(); ++it) {
101       val = *it;
102       *it = (val < t ? std::floor(val) : std::ceil(val));
103     }
104   }
105 
getParameter(const ROL::Vector<Real> & x) const106   ROL::Ptr<const std::vector<Real>> getParameter(const ROL::Vector<Real> &x) const {
107     try {
108       return dynamic_cast<const ROL::StdVector<Real>&>(x).getVector();
109     }
110     catch (std::exception &e) {
111       return dynamic_cast<const PDE_OptVector<Real>&>(x).getParameter()->getVector();
112     }
113   }
114 
getParameter(ROL::Vector<Real> & x) const115   ROL::Ptr<std::vector<Real>> getParameter(ROL::Vector<Real> &x) const {
116     try {
117       return dynamic_cast<ROL::StdVector<Real>&>(x).getVector();
118     }
119     catch (std::exception &e) {
120       return dynamic_cast<PDE_OptVector<Real>&>(x).getParameter()->getVector();
121     }
122   }
123 
124 public:
ADVDIFF_BranchSub(const ROL::Ptr<ROL::ROL_PEBBL_Branching<Real>> & branching,int verbosity=0,const ROL::Ptr<std::ostream> & outStream=ROL::nullPtr,int method=0)125   ADVDIFF_BranchSub(const ROL::Ptr<ROL::ROL_PEBBL_Branching<Real>> &branching,
126                     int verbosity = 0,
127                     const ROL::Ptr<std::ostream> &outStream = ROL::nullPtr,
128                     int method = 0)
129     : ROL::ROL_PEBBL_BranchSub<Real>(branching, verbosity, outStream), method_(method) {
130     switch (method_) {
131       case 1:  methodName_ = "Mass Preserving Rounding"; break;
132       case 2:  methodName_ = "Objective Gap Rounding";   break;
133       default: methodName_ = "Naive Rounding";
134     }
135   }
136 
ADVDIFF_BranchSub(const ADVDIFF_BranchSub & rpbs)137   ADVDIFF_BranchSub(const ADVDIFF_BranchSub &rpbs)
138     : ROL::ROL_PEBBL_BranchSub<Real>(rpbs), method_(rpbs.method_) {}
139 
incumbentHeuristic()140   void incumbentHeuristic() {
141     Real tol = std::sqrt(ROL::ROL_EPSILON<Real>());
142     Real t(0), val(0);
143     if (method_==1) { // mass preserving rounding
144       const Real zero(0), one(1);
145       rndSolution_->set(*solution_);
146       ROL::Ptr<std::vector<Real>> data = getParameter(*rndSolution_);
147       std::map<Real,size_t> sdata;
148       Real sum(0);
149       for (size_t i = 0; i < data->size(); ++i) {
150         sdata.insert(std::pair<Real,size_t>((*data)[i],i));
151         sum += (*data)[i];
152       }
153       int rsum = static_cast<int>(std::round(sum)), psum(0);
154       for (auto it = sdata.rbegin(); it != sdata.rend(); ++it) {
155         (*data)[it->second] = (psum < rsum ? one : zero);
156         t = (psum < rsum ? it->first : t);
157         psum++;
158       }
159     }
160     else if (method_==2) { // objective gap rounding
161       const Real invphi(0.5*(std::sqrt(5.0)-1.0));
162       const Real invphi2(0.5*(3.0-std::sqrt(5.0)));
163       const Real itol(std::sqrt(ROL::ROL_EPSILON<Real>()));
164       Real a(0), b(1), c(0), d(1), h(b-a), fc(0), fd(0);
165       // Evaluate at c
166       c = a + invphi2 * h;
167       round(*rndSolution_,*solution_,c);
168       problem0_->getObjective()->update(*rndSolution_);
169       fc = problem0_->getObjective()->value(*rndSolution_,tol);
170       // Evaluate at d
171       d = a + invphi * h;
172       round(*rndSolution_,*solution_,d);
173       problem0_->getObjective()->update(*rndSolution_);
174       fd = problem0_->getObjective()->value(*rndSolution_,tol);
175       while (std::abs(c-d) > itol) {
176         h *= invphi;
177         if (fc < fd) {
178           b  = d;
179           d  = c;
180           fd = fc;
181           c  = a + invphi2 * h;
182           round(*rndSolution_,*solution_,c);
183           problem0_->getObjective()->update(*rndSolution_);
184           fc = problem0_->getObjective()->value(*rndSolution_,tol);
185         }
186         else {
187           a  = c;
188           c  = d;
189           fc = fd;
190           d  = a + invphi * h;
191           round(*rndSolution_,*solution_,d);
192           problem0_->getObjective()->update(*rndSolution_);
193           fd = problem0_->getObjective()->value(*rndSolution_,tol);
194         }
195       }
196       t = static_cast<Real>(0.5)*(a+b);
197       round(*rndSolution_,*solution_,t);
198     }
199     else { // naive rounding
200       t = static_cast<Real>(0.5);
201       round(*rndSolution_,*solution_,t);
202     }
203     problem0_->getObjective()->update(*rndSolution_);
204     val = problem0_->getObjective()->value(*rndSolution_,tol);
205     branching_->foundSolution(new ROL::ROL_PEBBL_Solution<Real>(*rndSolution_,val));
206     if (verbosity_ > 0) {
207       *outStream_ << "ADVDIFF_BranchSub::incumbentHeuristic: " << methodName_ << std::endl;
208       *outStream_ << "  Incumbent Value:    " << val  << std::endl;
209       *outStream_ << "  Rounding Threshold: " << t    << std::endl;
210     }
211   };
212 
213 }; // class ADVDIFF_BranchSub
214 
215 #endif
216