/* $Id: ClpSolve.hpp 2078 2015-01-05 12:39:49Z forrest $ */ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Authors John Forrest */ #ifndef ClpSolve_H #define ClpSolve_H /** This is a very simple class to guide algorithms. It is used to tidy up passing parameters to initialSolve and maybe for output from that */ class ClpSolve { public: /** enums for solve function */ enum SolveType { useDual = 0, usePrimal, usePrimalorSprint, useBarrier, useBarrierNoCross, automatic, tryDantzigWolfe, tryBenders, notImplemented }; enum PresolveType { presolveOn = 0, presolveOff, presolveNumber, presolveNumberCost }; /**@name Constructors and destructor and copy */ //@{ /// Default constructor ClpSolve ( ); /// Constructor when you really know what you are doing ClpSolve ( SolveType method, PresolveType presolveType, int numberPasses, int options[6], int extraInfo[6], int independentOptions[3]); /// Generates code for above constructor void generateCpp(FILE * fp); /// Copy constructor. ClpSolve(const ClpSolve &); /// Assignment operator. This copies the data ClpSolve & operator=(const ClpSolve & rhs); /// Destructor ~ClpSolve ( ); //@} /**@name Functions most useful to user */ //@{ /** Special options - bits 0 4 - use crash (default allslack in dual, idiot in primal) 8 - all slack basis in primal 2 16 - switch off interrupt handling 3 32 - do not try and make plus minus one matrix 64 - do not use sprint even if problem looks good */ /** which translation is: which: 0 - startup in Dual (nothing if basis exists).: 0 - no basis 1 - crash 2 - use initiative about idiot! but no crash 1 - startup in Primal (nothing if basis exists): 0 - use initiative 1 - use crash 2 - use idiot and look at further info 3 - use sprint and look at further info 4 - use all slack 5 - use initiative but no idiot 6 - use initiative but no sprint 7 - use initiative but no crash 8 - do allslack or idiot 9 - do allslack or sprint 10 - slp before 11 - no nothing and primal(0) 2 - interrupt handling - 0 yes, 1 no (for threadsafe) 3 - whether to make +- 1matrix - 0 yes, 1 no 4 - for barrier 0 - dense cholesky 1 - Wssmp allowing some long columns 2 - Wssmp not allowing long columns 3 - Wssmp using KKT 4 - Using Florida ordering 8 - bit set to do scaling 16 - set to be aggressive with gamma/delta? 32 - Use KKT 5 - for presolve 1 - switch off dual stuff 6 - extra switches */ void setSpecialOption(int which, int value, int extraInfo = -1); int getSpecialOption(int which) const; /// Solve types void setSolveType(SolveType method, int extraInfo = -1); SolveType getSolveType(); // Presolve types void setPresolveType(PresolveType amount, int extraInfo = -1); PresolveType getPresolveType(); int getPresolvePasses() const; /// Extra info for idiot (or sprint) int getExtraInfo(int which) const; /** Say to return at once if infeasible, default is to solve */ void setInfeasibleReturn(bool trueFalse); inline bool infeasibleReturn() const { return independentOptions_[0] != 0; } /// Whether we want to do dual part of presolve inline bool doDual() const { return (independentOptions_[1] & 1) == 0; } inline void setDoDual(bool doDual_) { if (doDual_) independentOptions_[1] &= ~1; else independentOptions_[1] |= 1; } /// Whether we want to do singleton part of presolve inline bool doSingleton() const { return (independentOptions_[1] & 2) == 0; } inline void setDoSingleton(bool doSingleton_) { if (doSingleton_) independentOptions_[1] &= ~2; else independentOptions_[1] |= 2; } /// Whether we want to do doubleton part of presolve inline bool doDoubleton() const { return (independentOptions_[1] & 4) == 0; } inline void setDoDoubleton(bool doDoubleton_) { if (doDoubleton_) independentOptions_[1] &= ~4; else independentOptions_[1] |= 4; } /// Whether we want to do tripleton part of presolve inline bool doTripleton() const { return (independentOptions_[1] & 8) == 0; } inline void setDoTripleton(bool doTripleton_) { if (doTripleton_) independentOptions_[1] &= ~8; else independentOptions_[1] |= 8; } /// Whether we want to do tighten part of presolve inline bool doTighten() const { return (independentOptions_[1] & 16) == 0; } inline void setDoTighten(bool doTighten_) { if (doTighten_) independentOptions_[1] &= ~16; else independentOptions_[1] |= 16; } /// Whether we want to do forcing part of presolve inline bool doForcing() const { return (independentOptions_[1] & 32) == 0; } inline void setDoForcing(bool doForcing_) { if (doForcing_) independentOptions_[1] &= ~32; else independentOptions_[1] |= 32; } /// Whether we want to do impliedfree part of presolve inline bool doImpliedFree() const { return (independentOptions_[1] & 64) == 0; } inline void setDoImpliedFree(bool doImpliedfree) { if (doImpliedfree) independentOptions_[1] &= ~64; else independentOptions_[1] |= 64; } /// Whether we want to do dupcol part of presolve inline bool doDupcol() const { return (independentOptions_[1] & 128) == 0; } inline void setDoDupcol(bool doDupcol_) { if (doDupcol_) independentOptions_[1] &= ~128; else independentOptions_[1] |= 128; } /// Whether we want to do duprow part of presolve inline bool doDuprow() const { return (independentOptions_[1] & 256) == 0; } inline void setDoDuprow(bool doDuprow_) { if (doDuprow_) independentOptions_[1] &= ~256; else independentOptions_[1] |= 256; } /// Whether we want to do singleton column part of presolve inline bool doSingletonColumn() const { return (independentOptions_[1] & 512) == 0; } inline void setDoSingletonColumn(bool doSingleton_) { if (doSingleton_) independentOptions_[1] &= ~512; else independentOptions_[1] |= 512; } /// Whether we want to kill small substitutions inline bool doKillSmall() const { return (independentOptions_[1] & 8192) == 0; } inline void setDoKillSmall(bool doKill) { if (doKill) independentOptions_[1] &= ~8192; else independentOptions_[1] |= 8192; } /// Set whole group inline int presolveActions() const { return independentOptions_[1] & 0xffff; } inline void setPresolveActions(int action) { independentOptions_[1] = (independentOptions_[1] & 0xffff0000) | (action & 0xffff); } /// Largest column for substitution (normally 3) inline int substitution() const { return independentOptions_[2]; } inline void setSubstitution(int value) { independentOptions_[2] = value; } inline void setIndependentOption(int type,int value) { independentOptions_[type] = value; } inline int independentOption(int type) const { return independentOptions_[type]; } //@} ////////////////// data ////////////////// private: /**@name data. */ //@{ /// Solve type SolveType method_; /// Presolve type PresolveType presolveType_; /// Amount of presolve int numberPasses_; /// Options - last is switch for OsiClp int options_[7]; /// Extra information int extraInfo_[7]; /** Extra algorithm dependent options 0 - if set return from clpsolve if infeasible 1 - To be copied over to presolve options 2 - max substitution level If Dantzig Wolfe/benders 0 is number blocks, 2 is #passes (notional) */ int independentOptions_[3]; //@} }; /// For saving extra information to see if looping. class ClpSimplexProgress { public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor ClpSimplexProgress ( ); /// Constructor from model ClpSimplexProgress ( ClpSimplex * model ); /// Copy constructor. ClpSimplexProgress(const ClpSimplexProgress &); /// Assignment operator. This copies the data ClpSimplexProgress & operator=(const ClpSimplexProgress & rhs); /// Destructor ~ClpSimplexProgress ( ); /// Resets as much as possible void reset(); /// Fill from model void fillFromModel ( ClpSimplex * model ); //@} /**@name Check progress */ //@{ /** Returns -1 if okay, -n+1 (n number of times bad) if bad but action taken, >=0 if give up and use as problem status */ int looping ( ); /// Start check at beginning of whileIterating void startCheck(); /// Returns cycle length in whileIterating int cycle(int in, int out, int wayIn, int wayOut); /// Returns previous objective (if -1) - current if (0) double lastObjective(int back = 1) const; /// Set real primal infeasibility and move back void setInfeasibility(double value); /// Returns real primal infeasibility (if -1) - current if (0) double lastInfeasibility(int back = 1) const; /// Returns number of primal infeasibilities (if -1) - current if (0) int numberInfeasibilities(int back = 1) const; /// Modify objective e.g. if dual infeasible in dual void modifyObjective(double value); /// Returns previous iteration number (if -1) - current if (0) int lastIterationNumber(int back = 1) const; /// clears all iteration numbers (to switch off panic) void clearIterationNumbers(); /// Odd state inline void newOddState() { oddState_ = - oddState_ - 1; } inline void endOddState() { oddState_ = abs(oddState_); } inline void clearOddState() { oddState_ = 0; } inline int oddState() const { return oddState_; } /// number of bad times inline int badTimes() const { return numberBadTimes_; } inline void clearBadTimes() { numberBadTimes_ = 0; } /// number of really bad times inline int reallyBadTimes() const { return numberReallyBadTimes_; } inline void incrementReallyBadTimes() { numberReallyBadTimes_++; } /// number of times flagged inline int timesFlagged() const { return numberTimesFlagged_; } inline void clearTimesFlagged() { numberTimesFlagged_ = 0; } inline void incrementTimesFlagged() { numberTimesFlagged_++; } //@} /**@name Data */ #define CLP_PROGRESS 5 //#define CLP_PROGRESS_WEIGHT 10 //@{ /// Objective values double objective_[CLP_PROGRESS]; /// Sum of infeasibilities for algorithm double infeasibility_[CLP_PROGRESS]; /// Sum of real primal infeasibilities for primal double realInfeasibility_[CLP_PROGRESS]; #ifdef CLP_PROGRESS_WEIGHT /// Objective values for weights double objectiveWeight_[CLP_PROGRESS_WEIGHT]; /// Sum of infeasibilities for algorithm for weights double infeasibilityWeight_[CLP_PROGRESS_WEIGHT]; /// Sum of real primal infeasibilities for primal for weights double realInfeasibilityWeight_[CLP_PROGRESS_WEIGHT]; /// Drop for weights double drop_; /// Best? for weights double best_; #endif /// Initial weight for weights double initialWeight_; #define CLP_CYCLE 12 /// For cycle checking //double obj_[CLP_CYCLE]; int in_[CLP_CYCLE]; int out_[CLP_CYCLE]; char way_[CLP_CYCLE]; /// Pointer back to model so we can get information ClpSimplex * model_; /// Number of infeasibilities int numberInfeasibilities_[CLP_PROGRESS]; /// Iteration number at which occurred int iterationNumber_[CLP_PROGRESS]; #ifdef CLP_PROGRESS_WEIGHT /// Number of infeasibilities for weights int numberInfeasibilitiesWeight_[CLP_PROGRESS_WEIGHT]; /// Iteration number at which occurred for weights int iterationNumberWeight_[CLP_PROGRESS_WEIGHT]; #endif /// Number of times checked (so won't stop too early) int numberTimes_; /// Number of times it looked like loop int numberBadTimes_; /// Number really bad times int numberReallyBadTimes_; /// Number of times no iterations as flagged int numberTimesFlagged_; /// If things are in an odd state int oddState_; //@} }; #include "ClpConfig.h" #if CLP_HAS_ABC #include "AbcCommon.hpp" /// For saving extra information to see if looping. class AbcSimplexProgress : public ClpSimplexProgress { public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor AbcSimplexProgress ( ); /// Constructor from model AbcSimplexProgress ( ClpSimplex * model ); /// Copy constructor. AbcSimplexProgress(const AbcSimplexProgress &); /// Assignment operator. This copies the data AbcSimplexProgress & operator=(const AbcSimplexProgress & rhs); /// Destructor ~AbcSimplexProgress ( ); //@} /**@name Check progress */ //@{ /** Returns -1 if okay, -n+1 (n number of times bad) if bad but action taken, >=0 if give up and use as problem status */ int looping ( ); //@} /**@name Data */ //@} }; #endif #endif