10#ifndef ROL_PROGRESSIVEHEDGING_H
11#define ROL_PROGRESSIVEHEDGING_H
54class ProgressiveHedging {
56 const Ptr<Problem<Real>> input_;
57 const Ptr<SampleGenerator<Real>> sampler_;
58 ParameterList parlist_;
70 Ptr<PH_Objective<Real>> ph_objective_;
71 Ptr<Vector<Real>> ph_vector_;
72 Ptr<BoundConstraint<Real>> ph_bound_;
73 Ptr<Constraint<Real>> ph_constraint_;
74 Ptr<Problem<Real>> ph_problem_;
75 Ptr<Solver<Real>> ph_solver_;
76 Ptr<PH_StatusTest<Real>> ph_status_;
77 Ptr<Vector<Real>> z_psum_, z_gsum_;
78 std::vector<Ptr<Vector<Real>>> wvec_;
81 Solver<Real> solver(input_,parlist_);
82 for (
int j = 0; j < sampler_->numMySamples(); ++j) {
83 input_->getObjective()->setParameter(sampler_->getMyPoint(j));
84 if (input_->getConstraint() != nullPtr) {
85 input_->getConstraint()->setParameter(sampler_->getMyPoint(j));
88 z_psum_->axpy(sampler_->getMyWeight(j),*input_->getPrimalOptimizationVector());
93 sampler_->sumAll(*z_psum_,*z_gsum_);
97 ProgressiveHedging(
const Ptr<Problem<Real>> &input,
98 const Ptr<SampleGenerator<Real>> &sampler,
99 ParameterList &parlist)
100 : input_(input), sampler_(sampler), parlist_(parlist), hasStat_(false) {
102 usePresolve_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Use Presolve",
true);
103 useInexact_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Use Inexact Solve",
true);
104 penaltyParam_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Initial Penalty Parameter",10.0);
105 maxPen_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Maximum Penalty Parameter",-1.0);
106 update_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Penalty Update Scale",10.0);
107 freq_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Penalty Update Frequency",0);
108 ztol_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Nonanticipativity Constraint Tolerance",1e-4);
109 maxit_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Iteration Limit",100);
110 print_ = parlist.sublist(
"SOL").sublist(
"Progressive Hedging").get(
"Print Subproblem Solve History",
false);
111 maxPen_ = (maxPen_ <= static_cast<Real>(0) ? ROL_INF<Real>() : maxPen_);
112 penaltyParam_ = std::min(penaltyParam_,maxPen_);
114 ParameterList olist; olist.sublist(
"SOL") = parlist.sublist(
"SOL").sublist(
"Objective");
115 std::string type = olist.sublist(
"SOL").get(
"Type",
"Risk Neutral");
116 std::string prob = olist.sublist(
"SOL").sublist(
"Probability").get(
"Name",
"bPOE");
117 hasStat_ = ((type==
"Risk Averse") ||
118 (type==
"Deviation") ||
119 (type==
"Probability" && prob==
"bPOE"));
120 Ptr<ParameterList> parlistptr = makePtrFromRef<ParameterList>(olist);
122 ph_vector_ = makePtr<RiskVector<Real>>(parlistptr,
123 input_->getPrimalOptimizationVector());
126 ph_vector_ = input_->getPrimalOptimizationVector();
129 ph_objective_ = makePtr<PH_Objective<Real>>(input_->getObjective(),
135 ph_bound_ = makePtr<RiskBoundConstraint<Real>>(parlistptr,
136 input_->getBoundConstraint());
139 ph_bound_ = input_->getBoundConstraint();
142 ph_constraint_ = nullPtr;
143 if (input_->getConstraint() != nullPtr) {
145 ph_constraint_ = makePtr<RiskLessConstraint<Real>>(input_->getConstraint());
148 ph_constraint_ = input_->getConstraint();
152 ph_problem_ = makePtr<Problem<Real>>(ph_objective_, ph_vector_);
153 if (ph_bound_ != nullPtr) {
154 if (ph_bound_->isActivated()) {
155 ph_problem_->addBoundConstraint(ph_bound_);
158 if (ph_constraint_ != nullPtr) {
159 ph_problem_->addConstraint(
"PH Constraint",ph_constraint_,
160 input_->getMultiplierVector());
163 ph_solver_ = makePtr<Solver<Real>>(ph_problem_, parlist);
166 ph_status_ = makePtr<PH_StatusTest<Real>>(parlist,
170 ph_status_ = nullPtr;
173 z_psum_ = ph_problem_->getPrimalOptimizationVector()->clone();
174 z_gsum_ = ph_problem_->getPrimalOptimizationVector()->clone();
175 z_gsum_->set(*ph_problem_->getPrimalOptimizationVector());
176 wvec_.resize(sampler_->numMySamples());
177 for (
int i = 0; i < sampler_->numMySamples(); ++i) {
178 wvec_[i] = z_psum_->clone(); wvec_[i]->zero();
185 void check(std::ostream &outStream = std::cout,
const int numSamples = 1) {
186 int nsamp = std::min(sampler_->numMySamples(),numSamples);
187 for (
int i = 0; i < nsamp; ++i) {
188 ph_objective_->setParameter(sampler_->getMyPoint(i));
189 ph_objective_->setData(z_gsum_,wvec_[i],penaltyParam_);
190 if (ph_constraint_ != nullPtr) {
191 ph_constraint_->setParameter(sampler_->getMyPoint(i));
193 ph_problem_->check(
true,outStream);
197 void run(std::ostream &outStream = std::cout) {
199 std::vector<Real> vec_p(2), vec_g(2);
200 Real znorm(ROL_INF<Real>()), zdotz(0);
201 int iter(0), tspiter(0), flag = 1;
202 bool converged =
true;
204 outStream << std::scientific << std::setprecision(6);
205 outStream << std::endl <<
"Progressive Hedging"
207 << std::setw(8) << std::left <<
"iter"
208 << std::setw(15) << std::left <<
"||z-Ez||"
209 << std::setw(15) << std::left <<
"penalty"
210 << std::setw(10) << std::left <<
"subiter"
211 << std::setw(8) << std::left <<
"success"
213 for (iter = 0; iter < maxit_; ++iter) {
214 z_psum_->zero(); vec_p[0] =
zero; vec_p[1] =
zero;
215 ph_problem_->getPrimalOptimizationVector()->set(*z_gsum_);
217 for (
int j = 0; j < sampler_->numMySamples(); ++j) {
218 ph_objective_->setData(z_gsum_,wvec_[j],penaltyParam_);
219 ph_problem_->getObjective()->setParameter(sampler_->getMyPoint(j));
221 ph_status_->setData(iter,z_gsum_);
223 if (ph_problem_->getConstraint() != nullPtr) {
224 ph_problem_->getConstraint()->setParameter(sampler_->getMyPoint(j));
227 ph_solver_->solve(outStream,ph_status_,
true);
230 ph_solver_->solve(ph_status_,
true);
232 wvec_[j]->axpy(penaltyParam_,*ph_problem_->getPrimalOptimizationVector());
233 vec_p[0] += sampler_->getMyWeight(j)
234 *ph_problem_->getPrimalOptimizationVector()->dot(
235 *ph_problem_->getPrimalOptimizationVector());
236 vec_p[1] +=
static_cast<Real
>(ph_solver_->getAlgorithmState()->iter);
237 z_psum_->axpy(sampler_->getMyWeight(j),*ph_problem_->getPrimalOptimizationVector());
238 converged = (ph_solver_->getAlgorithmState()->statusFlag == EXITSTATUS_CONVERGED
239 ||ph_solver_->getAlgorithmState()->statusFlag == EXITSTATUS_USERDEFINED
240 ? converged :
false);
244 z_gsum_->zero(); vec_g[0] =
zero; vec_g[1] =
zero;
245 sampler_->sumAll(*z_psum_,*z_gsum_);
246 sampler_->sumAll(&vec_p[0],&vec_g[0],2);
248 for (
int j = 0; j < sampler_->numMySamples(); ++j) {
249 wvec_[j]->axpy(-penaltyParam_,*z_gsum_);
251 zdotz = z_gsum_->dot(*z_gsum_);
252 znorm = std::sqrt(std::abs(vec_g[0] - zdotz));
253 tspiter +=
static_cast<int>(vec_g[1]);
256 << std::setw(8) << std::left << iter
257 << std::setw(15) << std::left << znorm
258 << std::setw(15) << std::left << penaltyParam_
259 << std::setw(10) << std::left << static_cast<int>(vec_g[1])
260 << std::setw(8) << std::left << converged
263 if (znorm <= ztol_ && converged) {
265 outStream <<
"Converged: Nonanticipativity constraint tolerance satisfied!" << std::endl;
270 if (freq_ > 0 && iter%freq_ == 0) {
271 penaltyParam_ *= update_;
273 penaltyParam_ = std::min(penaltyParam_,maxPen_);
276 input_->getPrimalOptimizationVector()->set(*dynamicPtrCast<RiskVector<Real>>(z_gsum_)->getVector());
279 input_->getPrimalOptimizationVector()->set(*z_gsum_);
282 if (iter >= maxit_ && flag != 0) {
283 outStream <<
"Maximum number of iterations exceeded" << std::endl;
285 outStream <<
"Total number of subproblem iterations per sample: "
286 << tspiter <<
" / " << sampler_->numGlobalSamples()
287 <<
" ~ " <<
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)()