CNDSM
1.00
|
The SubGrad
class implements the NDOSolver interface for NonDifferentiable Optimization Solvers [see NDOSlver.h], using a unified subgradient-type algorithm as described in:
More...
#include <SubGrad.h>
Public Types | |
Public Types | |
![]() |
Public Member Functions | |
Constructor | |
SubGrad (istream *iStrm=0) | |
Constructor of the class. More... | |
Other initializations | |
void | SetStepsize (Stepsize *STP=0) |
Gives to the SubGrad object a pointer to an object of class Stepsize that will be used to provide ![]() | |
void | SetDeflection (Deflection *Vol=0) |
Gives to the SubGrad object a pointer to an object of class Deflection that will be used to provide a deflection coefficient ![]() | |
void | SetQKNP (CQKnPClass *KNP=0) |
Gives to the SubGrad object a pointer to an object of class CQKnPClass that will be used as quadratic knapsack solver during the subgradient algorithm. More... | |
void | SetFiOracle (FiOracle *Fi=0) |
void | SetLambda (cLMRow tLambda=0) |
void | KeepBestLambda (const bool KBL=true) |
void | SetPar (const int wp, const int value) |
Extends NDOSolver::SetPar( , cIndex ) for handling the SubGrad-specific parameters; the enum SGParam is used (in the obvious way) for selecting the parameter to be set. More... | |
void | SetPar (const int wp, cHpNum value) |
Extends NDOSolver::SetPar( , cHpNum ) for handling the SubGrad-specific parameters; the enum SGParam is used (in the obvious way) for selecting the parameter to be set. More... | |
void | SetPar (const int wp, const bool value) |
Change boolean algorithmic parameters of the SubGrad solver. More... | |
void | SetNDOLog (ostream *outs=0, const char lvl=0) |
lvl controls the "level of verbosity" of the code. More... | |
Solving the problem | |
NDOStatus | Solve (void) |
Tries to minimize the function [see NDOSlver.h]. More... | |
void | ReSetAlg (unsigned char RstLvl=0) |
Resets the internal state of the Subgradient algorithm. More... | |
Reading the solution | |
cLMRow | ReadBestSol (cIndex_Set &I, Index &D) |
Returns a read-only pointer to the point having the lowest ![]() | |
HpNum | ReadBestFiVal (cIndex wFi=Inf< Index >()) |
Returns the best ![]() | |
cLMRow | ReadSol (cIndex_Set &I, Index &D) |
Returns a read-only pointer to the stability center ![]() | |
HpNum | ReadFiVal (cIndex wFi=Inf< Index >()) |
Independently from which "component" of Fi() is chosen, it returns the full function Fi at the stability center ![]() | |
HpNum | ReadHatFiVal (void) |
Returns ![]() ![]() | |
bool | IsOptimal (HpNum eps=0) |
Returns true if the solution ![]() ![]() ![]() | |
cHpRow | ReadMult (cIndex_Set &I, Index &D, cIndex wFi=Inf< Index >()) |
HpNum | ReadLBMult (cIndex wFi=Inf< Index >()) |
Reading the data of the problem | |
void | GetPar (const int wp, int &value) |
void | GetPar (const int wp, HpNum &value) |
void | GetPar (const int wp, bool &value) |
Adding / removing / changing data | |
void | AddVariables (Index NNwVrs, cLMRow IVs=0) |
void | RemoveVariables (cIndex_Set whch=0, Index hwmny=0) |
void | ChgFiV (cIndex wFi=Inf< Index >()) |
void | ChgSbG (cIndex strt=0, Index stp=Inf< Index >(), cIndex wFi=Inf< Index >()) |
Destructor | |
~SubGrad () | |
![]() | |
virtual bool | IsOptimal (HpNum eps=0) const |
This method should return true if the NDOSolver believes that the current solution [see ReadSol() above] is eps-optimal (relative). More... | |
Index | FiEval (void) const |
Returns the number of times that Fi() has been called; if called from within Fi(), the present call should be excluded. More... | |
Index | GiEval (void) const |
Returns the number of times that NewGi() has been called; if called from within NewGi(), the present call should be excluded. More... | |
Index | NrCalls (void) const |
Returns the number of times that Solve() has been called; if called from within Solve(), the present call should be included. More... | |
Index | NrIter (void) const |
Returns the current number of iterations. More... | |
void | NDOTime (double &t_us, double &t_ss) |
If this method is called within any of the methods of the class that are "actively timed" (this depends on the subclasses), it returns the user and sistem time (in seconds) since the start of that method. More... | |
double | NDOTime (void) |
As NDOTime( double & , double & ) [see above], except that returns the total (system + user ) time. More... | |
NDOSolver (istream *iStrm=0) | |
Constructor of the class. More... | |
virtual void | SetNDOTime (const bool TimeIt=true) |
SetNDOTime() allocates an OPTtimers object [see OPTUtils.h] that should be used for timing the calls to relevant methods of the class. More... | |
Index | GetNumVar (void) const |
Returns the current number of variables of the function; a protected field is offered by the base class to keep this information. More... | |
virtual | ~NDOSolver () |
Destructor of the class. More... | |
Protected Member Functions | |
void | FiAndGi (cIndex wFi=Inf< Index >()) |
Evaluates the function at the new point ![]() ![]() ![]() | |
void | FormD (void) |
The method is used within Solve() [see above], and its job is to compute the direction ![]() ![]() | |
void | SaveDir (void) |
The method is combined with FormD() [see above] to carry out the direction computation. More... | |
void | GotoLambda1 (void) |
Move the current point to ![]() | |
void | FormLambda1 (void) |
After a (succesfull) call to FormD(), sets the new (unprojected) tentative point ![]()
Remark that the point | |
Protected Attributes | |
Index | SGPar1 |
projection-strategy parameters | |
HpNum | SGPar2 |
incremental factor | |
Index | SGPar3 |
scheme: stepsize(deflection)-restricted | |
bool | SGPar4 |
control if ![]() | |
Index | SGPar5 |
seed | |
Stepsize * | stepsize |
pointer to the Stepsize class | |
Deflection * | deflection |
pointer to the Deflection class | |
CQKnPClass * | Q2KNP |
pointer to the quadratic knapsack solver | |
Index | MaxNumVar |
maximum number of variables | |
Index | MaxNConst |
maximum number of simplex constraints | |
bool | BoxConst |
true, if there are some box constraints | |
LMRow | LambdaBar |
the stability center ![]() | |
HpNum | FiBar |
full function value at LambdaBar | |
LMRow | Lambda |
the current point ![]() ![]() | |
HpNum | FiLambda |
full function value at Lambda | |
LMRow | LambdaHat |
the point ![]() | |
HpNum | FiHat |
full function value at HLmb | |
bool | LHasChgd |
true if Lambda has changed since the latest call to FiAndGi() | |
bool | LHasProj |
true if Lambda has projected in the current iteration | |
bool | KpBstL |
if LambdaBest has to be kept | |
HpNum | FiBest |
the best value of ![]() | |
LMRow | LambdaBest |
the best point found so far | |
HpNum | LowerBound |
Lower Bound over the full function ![]() | |
bool | TrueLB |
true if LowerBound is a "true" lower bound rather than just the "minus infinity" | |
SgRow | Gi |
Gi[ wFi ]( Lambda ), the subgradient. | |
SgRow | dir |
the direction ![]() | |
HpNum | alpha |
the deflection parameter ![]() | |
HpNum | step |
the stepsize ![]() | |
HpNum | Sigma |
the linearization error ![]() ![]() ![]() | |
HpNum | Epsilon |
the linearization error ![]() ![]() ![]() | |
HpNum | SigmaHat |
the linearization error ![]() ![]() ![]() | |
HpNum | HatEpsilon |
the linearization error ![]() ![]() ![]() | |
Index_Set | SGBase |
the set of indices of Gi[ wFi ]( Lambda ) | |
Index | MaxName |
maximum name to be used in FiOracle->SetGiName() | |
HpNum | NrmGi |
the (squared) subgradient's norm | |
HpNum | NrmDir |
the (squared) direction's norm | |
HpNum | dGk |
scalar product between ![]() ![]() | |
HpNum | dM1Gk |
scalar product between ![]() ![]() | |
bool | dM1GkDone |
true if the scalar product ![]() | |
Index_Set | CnstBeg |
CnstBeg and CnstVol point respectively to a MaxNConst-vector of Index and HpNum, while CnstNxt is a MaxNumVar-vector of SIndex. More... | |
HpRow | CnstVol |
the MaxNConst-vector of HpNum containing the rhs of the knapsack Constraints | |
SIndex_Set | CnstNxt |
the MaxNumVar-vector of SIndex saying the next variable appearing in a knapsack constraint [see above] | |
LMRow | ub |
upper bounds on the variables | |
LMRow | lb |
lower bounds on the variables | |
bool | ZeroComp |
true if Fi() comes with the 0-th component | |
Index | NItIncr |
number of incremental iterations after an outer iteration | |
bool | InnIter |
if true, the current iteration is an inner one | |
vector< Index > | Seq |
vector containing the randomly shuffled components of the function ![]() | |
bool | DirPos |
indicates where the direction ![]() | |
Index | CSSCntr |
counter of consecutive SS | |
Index | CNSCntr |
counter of consecutive NS | |
Index | CSmallStep |
counter of consecutive short step | |
bool | DoSS |
SS vs NS. | |
FiOracle::FiStatus | fs |
FiOracle status. | |
bool | EmptySet |
true, if the feasible set is empty | |
![]() | |
FiOracle * | Oracle |
(pointer to) the oracle for Fi | |
Index | MaxIter |
maximum number of iterations | |
HpNum | MaxTime |
maximum time (in seconds) for each call to Solve() | |
HpNum | tStar |
optimality related parameter: "scaling" of Fi | |
HpNum | EpsLin |
optimality related parameter: relative precision | |
HpNum | EInit |
precision-related parameter: initial precision | |
HpNum | EFnal |
precision-related parameter: final precision | |
HpNum | EDcrs |
precision-related parameter: rate of decrease | |
int | EStps |
precision-related parameter: number of steps | |
NDOStatus | Result |
result of the latest call to Solve() | |
Index | NumVar |
(current) number of variables | |
Index | NrFi |
number of components of Fi() | |
Index | SCalls |
nuber of calls to Solve() (the current included) | |
Index | ParIter |
nuber of iterations in this run | |
Index | FiEvaltns |
total number of Fi() calls | |
Index | GiEvaltns |
total number of Gi() calls | |
ostream * | NDOLog |
the output stream object for log purposes | |
char | NDOLLvl |
the "level of verbosity" of the log | |
OPTtimers * | NDOt |
OPTtimer for timing purposes. | |
Friends | |
Friend classes | |
class | Stepsize |
The classes Stepsize and Deflection are "friends" of SubGrad. More... | |
class | Deflection |
The SubGrad
class implements the NDOSolver interface for NonDifferentiable Optimization Solvers [see NDOSlver.h], using a unified subgradient-type algorithm as described in:
A. Frangioni, E. Gorgone, B. Gendron. On the Computational Efficiency of Subgradient Methods: A Case Study in Combinatorial Optimization. Technical Report CIRRELT- 2015-41, Interuniversity Research Centre on Enterprise Networks, Logistics and Transportation (CIRRELT), Montreal, Canada, 2015
This is in fact a subgradient method (SM) based on abstract rules for the computation of both the stepsize and the direction
. The algorithm in employs the simple recurrence formula:
where denotes the orthogonal projection on
. The point
is not necessarily the current iterate. For instance, it could be required that
remains unchanged if an ascent direction occurs. It recalls somehow the stability center of the bundle methods.
The class relies on the objects of the friend classes Stepsize
and Deflection
, which have to return, respectively, the stepsize and the deflection coefficient
. The latter scalar number defines in turn the direction
, i.e..
. These abstract classes allow us to derive several variants of the method. For the sake of simplicity, the original SM characterized by
is performed setting the pointer to the object Deflection to NULL.
The class also includes the incremental variant for when the function to be maximized is composed by a sum of different functions.
enum SGParam |
Public enum which "extends" the enum NDOSolver::NDOParam for handling the SubGrad-specific algorithmic parameters in (the two overloaded versions of) SubGrad::SetPar() [see below].
SubGrad | ( | istream * | iStrm = 0 | ) |
Constructor of the class.
The parameter `iStrm', if provided, is taken as a pointer to a istream from which the algorithmic parameters for the subgradient algorithm are sequentially read in the following order. Each parameter must be placed at the beginning of a separate line, max 255 characters long, with all the rest of the line up to the first newline character (apart from a separating whitespace) being available for comments. Any line whose first character is '#' and any blank line is ignored. If 0 is passed, the file ends before reaching a given parameter, or some parameter is in the wrong format, each non-specified parameter is given a default value, shown in [] below.
`iStrm' is passed to the constructor of NDOSolver [see NDOSolver.h], which reads the general algorithmic parameters out of it; since the constructor SubGrad is executed after the one of NDOSolver, the following parameters specific for the SubGrad have to be found in the stream after those of the base class:
Index SGPar1 [0] The direction is assumed to be such a convex combination of the subgradient
and the direction
:
SGPar1 selects among the vector(s) to be projected over the tangent cone at
. The field SGPar1 is coded bit-wise, in the following way:
The setting (+7) is redundant. In fact, it is equivalent to (+3) because , being a (convex) combination of
and
, coincides with its projection.
void SetStepsize | ( | Stepsize * | STP = 0 | ) |
Gives to the SubGrad
object a pointer to an object of class Stepsize
that will be used to provide during the subgradient algorithm.
The Stepsize object can be changed during the life of a SubGrad object, but this change clearly forces the reset of all the information about the function accumulated so far. Passing a 0 pointer does exactly this job.
void SetDeflection | ( | Deflection * | Vol = 0 | ) |
Gives to the SubGrad
object a pointer to an object of class Deflection
that will be used to provide a deflection coefficient .
The Deflection object can be changed during the life of a SubGrad object, but this change clearly forces the reset of all the information about the function accumulated so far. Passing a 0 pointer does exactly this job.
In addition, 0 pointer means that the deflection coefficient is kept to 1, namely .
void SetQKNP | ( | CQKnPClass * | KNP = 0 | ) |
Gives to the SubGrad object a pointer to an object of class CQKnPClass that will be used as quadratic knapsack solver during the subgradient algorithm.
CQKnPClass object is employed to project the subgradient/direction when the projection problem is a continuous quadratic knapsack one. Moreover, the data of the problem are fixed just before the projection, hence no information is kept in the Subgradient method.
The CQKnPClass object can be changed during the life of a SubGrad object, but this change clearly implies that the prior object must be discharged. Passing a 0 pointer does exactly this job.
The default implementation assigns zero to the pointer of the CQKnPClass object directly in the constructor. In fact, CQKnPClass solver comes be helpful whenever in the feasible set the knapsack constraints appear. In contrast to what happens in both SetStepsize() and SetDeflection(), the call to the function SetQKNP() is mandatory only if knapsack constraints take place in the feasible set.
|
virtual |
Extends NDOSolver::SetPar( , cIndex ) for handling the SubGrad-specific parameters; the enum SGParam is used (in the obvious way) for selecting the parameter to be set.
Reimplemented from NDOSolver.
|
virtual |
Extends NDOSolver::SetPar( , cHpNum ) for handling the SubGrad-specific parameters; the enum SGParam is used (in the obvious way) for selecting the parameter to be set.
Reimplemented from NDOSolver.
void SetPar | ( | const int | wp, |
const bool | value | ||
) |
Change boolean algorithmic parameters of the SubGrad solver.
The enum SGParam [see above] is used for selecting the parameter to be set.
|
virtual |
lvl controls the "level of verbosity" of the code.
The first four bits of lvl have the following meaning:
Reimplemented from NDOSolver.
|
virtual |
Tries to minimize the function [see NDOSlver.h].
It implements the subgradient algorithm exploiting the protected methods FormD(), SaveDir(), FormLambda1(), FiAndGi(), GotoLambda1() [see below].
Returns if
As for kStopped, "too small" means that , where
is the optimality related parameter scaling Fi() [see NDOSlver.h]. There is no reason, in principle, why we couldn't replace
by a parameter, but in order to make the test easier this parameter has been fixed to
. We also decided to replace by 100 the parameter saying how many outer iterations of consecutive small stepsizes are sufficient to stop the algorithm.
Note that, whatever the exit condition be, the current point is always available by calling ReadSol(), and its Fi() value by calling ReadFiVal() [see below].
Implements NDOSolver.
|
virtual |
Resets the internal state of the Subgradient algorithm.
Since several different things can be reset independently, RstLvl is coded bit-wise:
Reimplemented from NDOSolver.
|
virtual |
Returns a read-only pointer to the point having the lowest value found so far [see below].
Reimplemented from NDOSolver.
|
virtual |
Returns the best value found so far.
Independently from which "component" of Fi() is chosen, it returns the full function.
Reimplemented from NDOSolver.
Referenced by ColorTV::ColorTV().
|
virtual |
Returns a read-only pointer to the stability center .
If Solve() has returned a kOK and the tStar has been properly set, the point returned by ReadSol() - and, a fortiori, the one returned by ReadBestSol() - is -optimal.
Implements NDOSolver.
HpNum ReadHatFiVal | ( | void | ) |
Returns , if
is kept in memory.
Otherwise it returns Inf<HpNum>().
bool IsOptimal | ( | HpNum | eps = 0 | ) |
Returns true if the solution is
-optimal (relative), being
set to EpsLin.
The parameter SGPar4 controls the linearization error to be used in the stopping condition:
SGPar4 = false: The criteria is just
where , i.e. the record value on the optimum $f_*$
|
protected |
Evaluates the function at the new point , i.e.,
, and it either computes a subgradient
, or, if the point is infeasible, a constraint.
|
protected |
The method is used within Solve() [see above], and its job is to compute the direction that appears in the formula of
.
The direction is actually saved after the variables generation because (i) the subgradient keeps in memory just the current direction (ii) by generating/removing variables the direction may quickly come to be deteriorated. When the variables generation is ended [see GetFiStatus() in FiOracle.h], SaveDir() must be called in order to update the direction.
In addition, the deflection coefficient is computed inside FormD(). As for the stepsize, the computation is performed within FormD() only if the scheme is deflection-restricted.
|
protected |
|
protected |
Move the current point to .
|
protected |
After a (succesfull) call to FormD(), sets the new (unprojected) tentative point as
Remark that the point must be projected before calling FiandGi() [see above], i.e.,
.
|
friend |
The classes Stepsize and Deflection are "friends" of SubGrad.
This is done because Stepsize and Deflection objects may need some protected data to work. An issue, however, is that derived classes from friend classes are not friend, and therefore actual implementations of Stepsize and Deflection cannot access data of SubGrad unless this capability is explicitly provided by the base classes, who are friends. This is why Stepsize and Deflection define a few methods that allow to read protected data of SubGrad: so that any derived class can use them to access to these data. These methods are, in fact, implemented at the end of SubGrad.C.
|
protected |
CnstBeg and CnstVol point respectively to a MaxNConst-vector of Index and HpNum, while CnstNxt is a MaxNumVar-vector of SIndex.
Each variable is associated to one and only knapsack constraint. CnstVol[ i ] is the volume of the i-th knapsack constraint. CnstBeg[ i ] supplies the starting of the i-th constraint, i.e. the first variable entering the i-th knpasack constraint. CnstNxt[ j ] says the name of the next variable to j entering the same knapsack constraint. If CnstNxt[ j ] == MaxNumVar, then no other variable enters that knapsack constraint, and if CnstNxt[ j ] == -1, the variable does not belong to any knapsack constraint.