44#ifndef ROL_PROGRESSIVEHEDGING_H
45#define ROL_PROGRESSIVEHEDGING_H
88class ProgressiveHedging {
90 const Ptr<Problem<Real>> input_;
91 const Ptr<SampleGenerator<Real>> sampler_;
92 ParameterList parlist_;
104 Ptr<PH_Objective<Real>> ph_objective_;
105 Ptr<Vector<Real>> ph_vector_;
106 Ptr<BoundConstraint<Real>> ph_bound_;
107 Ptr<Constraint<Real>> ph_constraint_;
108 Ptr<Problem<Real>> ph_problem_;
109 Ptr<Solver<Real>> ph_solver_;
110 Ptr<PH_StatusTest<Real>> ph_status_;
111 Ptr<Vector<Real>> z_psum_, z_gsum_;
112 std::vector<Ptr<Vector<Real>>> wvec_;
114 void presolve(
void) {
115 Solver<Real> solver(input_,parlist_);
116 for (
int j = 0; j < sampler_->numMySamples(); ++j) {
117 input_->getObjective()->setParameter(sampler_->getMyPoint(j));
118 if (input_->getConstraint() != nullPtr) {
119 input_->getConstraint()->setParameter(sampler_->getMyPoint(j));
122 z_psum_->axpy(sampler_->getMyWeight(j),*input_->getPrimalOptimizationVector());
127 sampler_->sumAll(*z_psum_,*z_gsum_);
131 ProgressiveHedging(
const Ptr<Problem<Real>> &input,
132 const Ptr<SampleGenerator<Real>> &sampler,
133 ParameterList &parlist)
134 : input_(input), sampler_(sampler), parlist_(parlist), hasStat_(false) {
136 usePresolve_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Use Presolve",
true);
137 useInexact_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Use Inexact Solve",
true);
138 penaltyParam_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Initial Penalty Parameter",10.0);
139 maxPen_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Maximum Penalty Parameter",-1.0);
140 update_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Penalty Update Scale",10.0);
141 freq_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Penalty Update Frequency",0);
142 ztol_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Nonanticipativity Constraint Tolerance",1e-4);
143 maxit_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Iteration Limit",100);
144 print_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Print Subproblem Solve History",
false);
145 maxPen_ = (maxPen_ <= static_cast<Real>(0) ? ROL_INF<Real>() : maxPen_);
146 penaltyParam_ = std::min(penaltyParam_,maxPen_);
148 ParameterList olist; olist.sublist(
"SOL") = parlist.sublist(
"SOL").sublist(
"Objective");
149 std::string type = olist.sublist(
"SOL").get(
"Type",
"Risk Neutral");
150 std::string prob = olist.sublist(
"SOL").sublist(
"Probability").get(
"Name",
"bPOE");
151 hasStat_ = ((type==
"Risk Averse") ||
152 (type==
"Deviation") ||
153 (type==
"Probability" && prob==
"bPOE"));
154 Ptr<ParameterList> parlistptr = makePtrFromRef<ParameterList>(olist);
156 ph_vector_ = makePtr<RiskVector<Real>>(parlistptr,
157 input_->getPrimalOptimizationVector());
160 ph_vector_ = input_->getPrimalOptimizationVector();
163 ph_objective_ = makePtr<PH_Objective<Real>>(input_->getObjective(),
169 ph_bound_ = makePtr<RiskBoundConstraint<Real>>(parlistptr,
170 input_->getBoundConstraint());
173 ph_bound_ = input_->getBoundConstraint();
176 ph_constraint_ = nullPtr;
177 if (input_->getConstraint() != nullPtr) {
179 ph_constraint_ = makePtr<RiskLessConstraint<Real>>(input_->getConstraint());
182 ph_constraint_ = input_->getConstraint();
186 ph_problem_ = makePtr<Problem<Real>>(ph_objective_, ph_vector_);
187 if (ph_bound_ != nullPtr) {
188 if (ph_bound_->isActivated()) {
189 ph_problem_->addBoundConstraint(ph_bound_);
192 if (ph_constraint_ != nullPtr) {
193 ph_problem_->addConstraint(
"PH Constraint",ph_constraint_,
194 input_->getMultiplierVector());
197 ph_solver_ = makePtr<Solver<Real>>(ph_problem_, parlist);
200 ph_status_ = makePtr<PH_StatusTest<Real>>(parlist,
204 ph_status_ = nullPtr;
207 z_psum_ = ph_problem_->getPrimalOptimizationVector()->clone();
208 z_gsum_ = ph_problem_->getPrimalOptimizationVector()->clone();
209 z_gsum_->set(*ph_problem_->getPrimalOptimizationVector());
210 wvec_.resize(sampler_->numMySamples());
211 for (
int i = 0; i < sampler_->numMySamples(); ++i) {
212 wvec_[i] = z_psum_->clone(); wvec_[i]->zero();
219 void check(std::ostream &outStream = std::cout,
const int numSamples = 1) {
220 int nsamp = std::min(sampler_->numMySamples(),numSamples);
221 for (
int i = 0; i < nsamp; ++i) {
222 ph_objective_->setParameter(sampler_->getMyPoint(i));
223 ph_objective_->setData(z_gsum_,wvec_[i],penaltyParam_);
224 if (ph_constraint_ != nullPtr) {
225 ph_constraint_->setParameter(sampler_->getMyPoint(i));
227 ph_problem_->check(
true,outStream);
231 void run(std::ostream &outStream = std::cout) {
233 std::vector<Real> vec_p(2), vec_g(2);
234 Real znorm(ROL_INF<Real>()), zdotz(0);
235 int iter(0), tspiter(0), flag = 1;
236 bool converged =
true;
238 outStream << std::scientific << std::setprecision(6);
239 outStream << std::endl <<
"Progressive Hedging"
241 << std::setw(8) << std::left <<
"iter"
242 << std::setw(15) << std::left <<
"||z-Ez||"
243 << std::setw(15) << std::left <<
"penalty"
244 << std::setw(10) << std::left <<
"subiter"
245 << std::setw(8) << std::left <<
"success"
247 for (iter = 0; iter < maxit_; ++iter) {
248 z_psum_->zero(); vec_p[0] =
zero; vec_p[1] =
zero;
249 ph_problem_->getPrimalOptimizationVector()->
set(*z_gsum_);
251 for (
int j = 0; j < sampler_->numMySamples(); ++j) {
252 ph_objective_->setData(z_gsum_,wvec_[j],penaltyParam_);
253 ph_problem_->getObjective()->setParameter(sampler_->getMyPoint(j));
255 ph_status_->setData(iter,z_gsum_);
257 if (ph_problem_->getConstraint() != nullPtr) {
258 ph_problem_->getConstraint()->setParameter(sampler_->getMyPoint(j));
261 ph_solver_->solve(outStream,ph_status_,
true);
264 ph_solver_->solve(ph_status_,
true);
266 wvec_[j]->axpy(penaltyParam_,*ph_problem_->getPrimalOptimizationVector());
267 vec_p[0] += sampler_->getMyWeight(j)
268 *ph_problem_->getPrimalOptimizationVector()->dot(
269 *ph_problem_->getPrimalOptimizationVector());
270 vec_p[1] +=
static_cast<Real
>(ph_solver_->getAlgorithmState()->iter);
271 z_psum_->axpy(sampler_->getMyWeight(j),*ph_problem_->getPrimalOptimizationVector());
272 converged = (ph_solver_->getAlgorithmState()->statusFlag == EXITSTATUS_CONVERGED
273 ||ph_solver_->getAlgorithmState()->statusFlag == EXITSTATUS_USERDEFINED
274 ? converged :
false);
278 z_gsum_->zero(); vec_g[0] =
zero; vec_g[1] =
zero;
279 sampler_->sumAll(*z_psum_,*z_gsum_);
280 sampler_->sumAll(&vec_p[0],&vec_g[0],2);
282 for (
int j = 0; j < sampler_->numMySamples(); ++j) {
283 wvec_[j]->axpy(-penaltyParam_,*z_gsum_);
285 zdotz = z_gsum_->
dot(*z_gsum_);
286 znorm = std::sqrt(std::abs(vec_g[0] - zdotz));
287 tspiter +=
static_cast<int>(vec_g[1]);
290 << std::setw(8) << std::left << iter
291 << std::setw(15) << std::left << znorm
292 << std::setw(15) << std::left << penaltyParam_
293 << std::setw(10) << std::left << static_cast<int>(vec_g[1])
294 << std::setw(8) << std::left << converged
297 if (znorm <= ztol_ && converged) {
299 outStream <<
"Converged: Nonanticipativity constraint tolerance satisfied!" << std::endl;
304 if (freq_ > 0 && iter%freq_ == 0) {
305 penaltyParam_ *= update_;
307 penaltyParam_ = std::min(penaltyParam_,maxPen_);
310 input_->getPrimalOptimizationVector()->set(*dynamicPtrCast<RiskVector<Real>>(z_gsum_)->getVector());
313 input_->getPrimalOptimizationVector()->set(*z_gsum_);
316 if (iter >= maxit_ && flag != 0) {
317 outStream <<
"Maximum number of iterations exceeded" << std::endl;
319 outStream <<
"Total number of subproblem iterations per sample: "
320 << tspiter <<
" / " << sampler_->numGlobalSamples()
321 <<
" ~ " <<
static_cast<int>(std::ceil(
static_cast<Real
>(tspiter)/
static_cast<Real
>(sampler_->numGlobalSamples())))
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0 zero)()
virtual void set(const Vector &x)
Set where .
virtual Real dot(const Vector &x) const =0
Compute where .