NDOSolver / FiOracle
Interfaces and Solvers for NonDifferentiable Optimization
Loading...
Searching...
No Matches
TestFi Class Reference
Inheritance diagram for TestFi:
FiOracle

Public Member Functions

 TestFi (cIndex NV, cLMNum L0)
 
virtual HpNum Fi (cIndex wFi=Inf< Index >()) override final
 
virtual Index GetGi (SgRow SubG, cIndex_Set &SGBse, cIndex Name=Inf< Index >(), cIndex strt=0, Index stp=Inf< Index >()) override final
 
virtual HpNum GetLowerBound (cIndex wFi=Inf< Index >()) override final
 
virtual ~TestFi ()
 destructor of the class: it must be virtual
 
- Public Member Functions inherited from FiOracle
virtual NDOSolverGetNDOSolver (void)
 
 FiOracle (void)
 
virtual void SetNDOSolver (NDOSolver *NwSlvr=0)
 
virtual void SetFiLog (ostream *outs=0, const char lvl=0)
 
virtual void SetFiTime (const bool TimeIt=true)
 
virtual void SetMaxName (cIndex MxNme=0)
 
virtual Index GetNumVar (void) const
 
virtual Index GetMaxNumVar (void) const
 
virtual Index GetNrFi (void) const
 
virtual Index MaxNConst (void)
 
virtual bool IsFiContinuous (cIndex NrFi=Inf< Index >())
 
virtual bool IsFiConvex (cIndex NrFi=Inf< Index >())
 
virtual bool HasGi (cIndex NrFi=Inf< Index >())
 
virtual bool IsGiContinuous (cIndex NrFi)
 
virtual bool HasH (cIndex NrFi)
 
virtual bool IsHContinuous (cIndex NrFi)
 
virtual Index GetMaxName (void) const
 
virtual HpNum GetMinusInfinity (void)
 
virtual Index GetMaxNZ (cIndex wFi=Inf< Index >()) const
 
virtual Index GetMaxCNZ (cIndex wFi=Inf< Index >()) const
 
virtual bool GetUC (cIndex i)
 
virtual LMNum GetUB (cIndex i)
 
virtual LMNum GetBndEps (void)
 
virtual HpNum GetGlobalLipschitz (cIndex wFi=Inf< Index >())
 
virtual Index GetBNC (cIndex wFi)
 
virtual Index GetBNR (cIndex wFi)
 
virtual Index GetBNZ (cIndex wFi)
 
virtual void GetBDesc (cIndex wFi, int *Bbeg, int *Bind, double *Bval, double *lhs, double *rhs, double *cst, double *lbd, double *ubd)
 
virtual Index GetANZ (cIndex wFi, cIndex strt=0, Index stp=Inf< Index >())
 
virtual void GetADesc (cIndex wFi, int *Abeg, int *Aind, double *Aval, cIndex strt=0, Index stp=Inf< Index >())
 
virtual void SetLambda (cLMRow Lmbd=0)
 
virtual void SetLamBase (cIndex_Set LmbdB=0, cIndex LmbdBD=0)
 
virtual bool SetPrecision (HpNum Eps)
 
virtual bool NewGi (cIndex wFi=Inf< Index >())
 
virtual HpNum GetVal (cIndex Name=Inf< Index >())
 
virtual void SetGiName (cIndex Name)
 
virtual FiStatus GetFiStatus (Index wFi=Inf< Index >())
 
void FiTime (double &t_us, double &t_ss)
 
double FiTime (void)
 
virtual void Deleted (cIndex i=Inf< Index >())
 
virtual void Aggregate (cHpRow Mlt, cIndex_Set NmSt, cIndex Dm, cIndex NwNm)
 
virtual ~FiOracle ()
 

Protected Attributes

LMNum Cntr
 
- Protected Attributes inherited from FiOracle
NDOSolverSlvr
 
Index NumVar
 (current) number of variables if Fi()
 
Index MaxName
 maximum name to be used in SetGiName()
 
cLMRow Lambda
 
cIndex_Set LamBase
 
Index LamBDim
 length of LamBase[]
 
bool LHasChgd
 
ostream * FiLog
 the output stream object for log purposes
 
char FiLLvl
 the "level of verbosity" of the log
 
OPTtimersFit
 OPTtimer for timing purposes.
 

Additional Inherited Members

- Public Types inherited from FiOracle
enum  FiStatus {
  kFiNorm = 0 , kFiError , kFiChgd , kFiStop ,
  kFiCont
}
 

Constructor & Destructor Documentation

◆ TestFi()

TestFi ( cIndex NV,
cLMNum L0 )

NV is the number of variables, and L0 the "center" of the function; these parameters are only needed for the sake of! this example: remove them and replace with your own.

Member Function Documentation

◆ Fi()

virtual HpNum Fi ( cIndex wFi = InfIndex >())
finaloverridevirtual

This method must return the value of the function Fi to be minimized in the point Lmbd set by SetLambda() and SetLamBase() [see above]. Usually, Fi() has to be called after SetLambda(), the only exception being if Fi( < all-zero vector > ) is required, since Lambda == all-zero is the default assumed if SetLambda() is not called.

wFi tells the value of which of the components of Fi() [see GetNrFi() above] has to be returned. Note that all functions, even those that are declared non-separable (GetNrFi() == 1), are treated as the sum of a generic function Fi[ 1 ]( Lambda ) plus a linear function b * Lambda; this is always possible (b can be == 0). The meaning of wFi is:

  • wFi == 0 requires the value of the linear (affine) 0-th component of Fi.
  • 1 <= wFi <= GetNrFi() requires the value of the wFi-th component of Fi, which must not be an "easy" one [see GetBNC() etc. above];
  • Inf< Index >() > wFi > GetNrFi() requires the value of the full function Fi except that of the "easy" components [see GetBNC() etc. above] and of the linear part, i.e. Sum{h = 1 .. GetNrFi(), h not easy} Fi( h ).
  • wFi == Inf< Index >() requires the value of the full function Fi except that of the "easy" components (...).

In case an error occurs in the calculation of Fi(), this can be signalled immediately by returning - INF (a proper convex function never evaluates to - Infinity); if a "decent" value is available, an alternative is to use GetFiStatus() [see below]. Note that an important special case exists when it may be reasonable for a FiOracle to return - INF; this is when (one component of) Fi() is not a proper convex function, that is, it is identically equal to - Infinity*. In the Lagrangian case, this corresponds to the fact that (one of) the Lagrangian problem(s) actually is empty. It is for this reason that if Fi() returns - INF, then the NDO solver has the right to declare Fi() unbounded below.

Fi() may also return + INF, meaning that the point set by SetLambda() is outside the feasible region (the domain of the function to be minimized). In this case, the information returned by GetGi() [see below] has a different meaning. However, note that, when Fi is separable, only some of its components may be undefined, while other may still give valid subgradients; in other words, the point set by SetLambda() may belong to Dom( Fi[ h ] ) for some h, and not for others. Thus, as for subgradients, when a constraint is generated the value of wFi in the call to Fi() which returned INF allows the NDOSolver to distinguish to which component the constraint belongs to.

Usually, there will be only one call to Fi() (for each component) for each call to SetLambda(); however, multiple calls are allowed if the "precision" changes [see SetPrecision() above].

Implements FiOracle.

◆ GetGi()

virtual Index GetGi ( SgRow SubG,
cIndex_Set & SGBse,
cIndex Name = InfIndex >(),
cIndex strt = 0,
Index stp = InfIndex >() )
finaloverridevirtual

GetGi() [and GetVal(), see below] can be used to query information about the items. The method allows to access both the newly produced item corresponding to the last call to NewGi() [see above], if it has not been "named" yet [see SetGiName() below], and all "named" items recorded in the FiOracle memory, if any [see SetMaxName() above]. This is specified by the value of Name. If Name < n, where n is the max name set by the latest call to SetMaxName(), then the required information is about the item Name. Note that Name must be a valid item name, i.e., a name that has been previously used in some call to SetGiName(), and not used in any call to Deleted() after the last call of SetGiName() where it was used. If Name == n, then the required information is about the constant subgradient of the linear 0-th component of Fi. Finally, if Name > n then the required information is about the newly produced "unnamed" item. Note that, given Name, it is immediately known to which component of Fi the associated item belongs.

GetGi() can be used to retrieve (part of) the linear GetNumVar()-vector which characterizes the item. SubG is a pointer to a vector of SgNum of appropriate length (see below) where the item have to be written. The indices strt and stp tell that what is required is the part of the vector corresponding to variables with "names" comprised between strt (included) and min{ stp , GetNumVar() } (excluded); the name of a variable is just its position in the vector Lmbd. Upon return, the required information has to be written in SubG; the "format" of SubG depends on what is returned in the read-only pointer SGBse. If SGBse == 0, then SubG[] is in "dense" format, i.e., SubG[ i ] is the entry of the subgradient relative to variable strt + i for i in 0 .. min( GetNumVar() , stp ) - strt. If SGBse != 0, then it must point to the vector of indices of nonzero entries of the subgradient (ordered in increasing sense and Inf< Index >()-terminated). That is, for i = strt ... stp - 1, the "real" SubG is

            / SubG[ j ]    if exists j < k s.t. SGBse[ j ] = i

SubG[ i ] = | \ 0 otherwise.

where k, the number of nonzeroes of SubG[], is returned by GetGi(). If SGBse == 0, then GetGi() should return min{ stp , GetNumVar() } - strt, i.e., the length of the "dense" SubG[]. Note that, if SGBse != 0, the Indices in SGBse[] are in the range [strt, min{ stp , GetNumVar() }).

According to whether the item is a subgradient or a constraint (which is revealed by the return value of Fi()), GetMaxNZ( wFi ) and GetMaxCNZ( wFi ) [see above] provide an upper bound on the maximum number of nonzeroes in the item; let us denote that by MxNZ. Then, the length of the vector SubG is required to be at least

min( MxNZ , min( GetNumVar() , stp ) - strt ) ,

i.e., the minimum possible amount that is guaranteed to contain all the possible nonzeroes. Hence, a non-0 SGBDim must always be returned if MxNZ < min( GetNumVar() , stp ) - strt ), as in this case the vector SubG is not long enough to accommodate (the required part of) an item in "dense" format. Also, note that the memory for SGBase has to be provided by the FiOracle, but the NDO solver is not allowed to keep the pointer and must copy the vector, if it so requires, because the content may change at the subsequent call to any method of the FiOracle.

Allowing a NDO solver to query information about items "stored" in the FiOracle [see SetGiName() below] has different uses. For instance, the NDO solver may use variables generation techniques which try to solve a NDO problem by restricting it to a (small) "active set" of the variables, minimizing the function in that subspace and possibly revising the active set. Thus, at some point the NDO solver may not need some of the information related to an item, but this information may still be required later. A possibly more important use, however, is tied to the handling of changes in the function, which may occur in applications as those alluded to in the general notes. The implementation of the methods AddVariables() and ChgSbG() of NDOSolver [see NDOSlver.h] typically require calls to GetGi() to get information about some components of the items "stored" in the FiOracle. Note that these methods of class NDOSolver, in turn, can be called by the FiOracle itself, e.g. in the method GetFiStatus() [see below], so that the FiOracle may well be "prepared" when a call occurs simply because the caller was, ultimately, itself.

Implements FiOracle.

◆ GetLowerBound()

virtual HpNum GetLowerBound ( cIndex wFi = InfIndex >())
inlinefinaloverridevirtual

In some cases, a Lower Bound on the minimal value of Fi is known; if Fi is a Lagrangian function, for instance, the objective function value c( x ) of any dual feasible solution x (s.t. A( x ) [<]= b and x \in X) gives a valid lower bound. This value can be useful for NDO solver, especially if it is tight; for one thing, it ensures that the function is not unbounded below.

GetLowerBound() allows to retrieve this value from the FiOracle, which may return - INF to signal that no Lower Bound is known. Note that the value may change—typically, increase—over time, e.g. as better feasible solutions of the dual problem are generated, so that it may be worth to call GetLowerBound() after each call to Fi() to check if a better bound has become available. Of course, the value returned by GetLowerBound() must be no smaller than that returned by GetMinusInfinity() [see above], although the two can be equal.

Furthermore, changes in Fi() (number of variables etc.) may possibly render any previously obtained Lower Bound invalid, so that this method should be called at least each time Fi() changes; failure to do that could lead to early and incorrect termination of the optimization due to the use of an incorrect Lower Bound.

Lower Bounds may be available separately for the wFi-th component of Fi, 1 <= wFi <= GetNrFi(); these are returned by GetLowerBound( wFi ). Note that if wFi is an "easy" component then it makes no sense to provide an explicit lower bound, since everything is known for that component and the Lower Bound, if any, is already implicit in the description; thus, GetLowerBound( wFi ) should always return - INF if wFi is "easy". GetLowerBound( 0 ) also makes no sense (i.e., - INF is again a good return value) while GetLowerBound( wFi ) for wFi > NrFi must return a "global" Lower Bound for the whole Fi.

Note
While "individual" Lower Bounds are not allowed for "easy" components, the "global" Lower Bound is to be intended as a bound on the total value of Fi(), that is, comprised the value of the "easy" components.
The existence of a "global" Lower Bound does not imply the existence of "individual" Lower Bounds; consider the case of the 0-th linear component of Fi, which has no Lower Bound unless the domain of Fi is compact. Vice-versa, "individual" Lower Bounds imply a "global" one only if every component has one comprised the 0-th (i.e., the 0-th component is bounded on the domain, e.g. it is null or the domain is bounded).

Reimplemented from FiOracle.

Member Data Documentation

◆ Cntr

LMNum Cntr
protected

the minimum of the function (L0): this protected data structure is only needed for the sake of this example, remove it and replace with your own.


The documentation for this class was generated from the following file: