// $Id: CbcHeuristicDW.hpp 1899 2013-04-09 18:12:08Z stefan $
// Copyright (C) 2006, International Business Machines
// Corporation and others.  All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).

#ifndef CbcHeuristicDW_H
#define CbcHeuristicDW_H

#include "CbcHeuristic.hpp"

/** 
    This is unlike the other heuristics in that it is very very compute intensive.
    It tries to find a DW structure and use that
 */

class CbcHeuristicDW : public CbcHeuristic {
public:
  // Default Constructor
  CbcHeuristicDW();

  /* Constructor with model - assumed before cuts
    */
  CbcHeuristicDW(CbcModel &model, int keepContinuous = 0);

  /* Constructor with model - assumed before cuts
    */
  CbcHeuristicDW(CbcModel &model,
    int callBack(CbcHeuristicDW *currentHeuristic,
      CbcModel *thisModel,
      int whereFrom),
    int keepContinuous = 0);

  // Copy constructor
  CbcHeuristicDW(const CbcHeuristicDW &);

  // Destructor
  ~CbcHeuristicDW();

  /// Clone
  virtual CbcHeuristic *clone() const;

  /// Assignment operator
  CbcHeuristicDW &operator=(const CbcHeuristicDW &rhs);

  /// Create C++ lines to get to current state
  virtual void generateCpp(FILE *fp);

  /// Resets stuff if model changes
  virtual void resetModel(CbcModel *model);

  /// update model (This is needed if cliques update matrix etc)
  virtual void setModel(CbcModel *model);
  using CbcHeuristic::solution;
  /** returns 0 if no solution, 1 if valid solution.
        Sets solution values if good, sets objective value (only if good)
        This does Relaxation Induced Neighborhood Search
    */
  virtual int solution(double &objectiveValue,
    double *newSolution);
  /** Return number of blocks
      <=0 - no usable structure */
  inline int numberBlocks() const
  {
    return numberBlocks_;
  }
  /// Pass in a solution
  void passInSolution(const double *solution);
  /// Pass in continuous solution
  void passInContinuousSolution(const double *solution);
  /** DW Proposal actions
        fullDWEverySoOften -
        0 - off
        k - every k times solution gets better
     */
  void setProposalActions(int fullDWEverySoOften);
  /// Objective value when whichDw created
  double objectiveValueWhen(int whichDW) const;
  /// Number of columns in DW
  int numberColumnsDW(int whichDW) const;
  /// Solver
  inline OsiSolverInterface *solver() const
  {
    return solver_;
  }
  /// DW model (user must delete)
  OsiSolverInterface *DWModel(int whichDW) const;
  /// Best objective value
  inline double bestObjective() const
  {
    return bestObjective_;
  }
  /// Best solution found so far
  inline const double *bestSolution() const
  {
    return bestSolution_;
  }
  /// Continuous solution
  inline const double *continuousSolution() const
  {
    return continuousSolution_;
  }
  /// Reduced costs of fixed solution
  inline const double *fixedDj() const
  {
    return fixedDj_;
  }
  /// Objective at which DW updated
  inline const double *objectiveDW() const
  {
    return objectiveDW_;
  }
  /// Number of times we have added to DW model
  inline int numberDWTimes() const
  {
    return numberDWTimes_;
  }
  /// Number of columns in DW
  inline const int *numberColumnsDW() const
  {
    return numberColumnsDW_;
  }
  /// Set number of passes
  inline void setNumberPasses(int value)
  {
    numberPasses_ = value;
  }
  /// Set number of passes without better solution
  inline void setNumberBadPasses(int value)
  {
    numberBadPasses_ = value;
  }
  /// Set number free integers needed (Base value)
  inline void setNumberNeeded(int value)
  {
    nNeededBase_ = value;
  }
  /// Get number free integers needed (Base value)
  inline int getNumberNeeded() const
  {
    return nNeededBase_;
  }
  /// Set number free integers needed (Current value)
  inline void setCurrentNumberNeeded(int value)
  {
    nNeeded_ = value;
  }
  /// Get number free integers needed (Current value)
  inline int getCurrentNumberNeeded() const
  {
    return nNeeded_;
  }
  /// Set number nodes (could be done in callback) (Base value)
  inline void setNumberNodes(int value)
  {
    nNodesBase_ = value;
  }
  /// Get number nodes (could be done in callback) (Base value)
  inline int getNumberNodes() const
  {
    return nNodesBase_;
  }
  /// Set number nodes (could be done in callback) (Current value)
  inline void setCurrentNumberNodes(int value)
  {
    nNodes_ = value;
  }
  /// Get number nodes (could be done in callback) (Current value)
  inline int getCurrentNumberNodes() const
  {
    return nNodes_;
  }
  /// Set target objective
  inline void setTargetObjective(double value)
  {
    targetObjective_ = value;
  }
  /// Sets how often to do it
  inline void setHowOften(int value)
  {
    howOften_ = value;
  }
  /// Block for every row
  inline const int *whichRowBlock() const
  {
    return whichRowBlock_;
  }
  /// Block for every column
  inline const int *whichColumnBlock() const
  {
    return whichColumnBlock_;
  }
  /// Initial Lower bounds
  inline double *initialLower() const
  {
    return saveLower_;
  }
  /// Initial Upper bounds
  inline double *initialUpper() const
  {
    return saveUpper_;
  }
  /// Local integer arrays (each numberBlocks_ long)
  inline int *intArrays() const
  {
    return intArray_;
  }
  /// Local double arrays (each numberBlocks_ long)
  inline double *doubleArrays() const
  {
    return doubleArray_;
  }
  /// Phase of solution
  inline int phase() const
  {
    return phase_;
  }
  /// Pass number
  inline int pass() const
  {
    return pass_;
  }
  /// Which columns are in block
  inline const int *columnsInBlock() const
  {
    return columnsInBlock_;
  }
  /// Starts for columnsInBlock
  inline const int *startColumnBlock() const
  {
    return startColumnBlock_;
  }
  /// Number of integer variables in each block
  inline const int *intsInBlock() const
  {
    return intsInBlock_;
  }
  /// Objective value (could also check validity)
  double objectiveValue(const double *solution);

private:
  /// Guts of copy
  void gutsOfCopy(const CbcHeuristicDW &rhs);
  /// Guts of delete
  void gutsOfDelete();
  /// Set default values
  void setDefaults();
  /// Find structure
  void findStructure();
  /// Set up DW structure
  void setupDWStructures();
  /// Add DW proposals
  int addDW(const double *solution, int numberBlocksUsed,
    const int *whichBlocks);

protected:
  typedef int (*heuristicCallBack)(CbcHeuristicDW *, CbcModel *, int);
  // Data
  /// Target objective
  double targetObjective_;
  /// Best objective value
  double bestObjective_;
  /// Objective value last time
  double lastObjective_;
  /** Call back
	whereFrom -
	0 - after blocks found but before data setup
	1 - after blocks sorted but before used
	2 - just before normal branch and bound
	3 - after DW has been updated
	4 - if better solution found
	5 - every time a block might be used
	next few for adjustment of nNeeded etc
	6 - complete search done - no solution
	7 - stopped on nodes - no improvement
	8 - improving (same as 4 but after nNeeded changed
	Pointers to local data given by following pointers
    */
  heuristicCallBack functionPointer_;
  /// Local integer arrays (each numberBlocks_ long)
  int *intArray_;
  /// Local double arrays (each numberBlocks_ long)
  double *doubleArray_;
  /// Base solver
  OsiSolverInterface *solver_;
  /// DW solver
  OsiSolverInterface *dwSolver_;
  /// Best solution found so far
  double *bestSolution_;
  /// Continuous solution
  double *continuousSolution_;
  /// Reduced costs of fixed solution
  double *fixedDj_;
  /// Original lower bounds
  double *saveLower_;
  /// Original Upper bounds
  double *saveUpper_;
  /// random numbers for master rows
  double *random_;
  /// Weights for each proposal
  double *weights_;
  /// Objective at which DW updated
  double *objectiveDW_;
  /// Number of columns in each DW
  int *numberColumnsDW_;
  /// Block for every row
  int *whichRowBlock_;
  /// Block for every column
  int *whichColumnBlock_;
  /// Block number for each proposal
  int *dwBlock_;
  /// Points back to master rows
  int *backwardRow_;
  /// Which rows are in blocke
  int *rowsInBlock_;
  /// Which columns are in block
  int *columnsInBlock_;
  /// Starts for rowsInBlock
  int *startRowBlock_;
  /// Starts for columnsInBlock
  int *startColumnBlock_;
  /// Number of integer variables in each block
  int *intsInBlock_;
  /// Bits set for 1 integers in each block
  unsigned int *fingerPrint_;
  /// Affinity each block has for other (will be triangular?)
  unsigned short *affinity_;
  /** DW Proposal actions
        fullDWEverySoOften -
        0 - off
        k - every k times solution gets better
     */
  int fullDWEverySoOften_;
  /// Number of passes
  int numberPasses_;
  /// How often to do (code can change)
  int howOften_;
  /// Current maximum number of DW proposals
  int maximumDW_;
  /// Number of DW proposals
  int numberDW_;
  /// Number of times we have added to DW model
  int numberDWTimes_;
  /// Number of unsigned ints needed for each block of fingerPrint
  int sizeFingerPrint_;
  /// Number of columns in master
  int numberMasterColumns_;
  /// Number of rows in master
  int numberMasterRows_;
  /// Number of blocks
  int numberBlocks_;
  /// Action on decomposition - 1 keep continuous, 0 don't
  int keepContinuous_;
  /// Phase of solution
  int phase_;
  /// Pass number
  int pass_;
  /// Base number of integers needed
  int nNeededBase_;
  /// Base number of nodes needed
  int nNodesBase_;
  /// Base number of integers needed
  int nNeeded_;
  /// Base number of nodes needed
  int nNodes_;
  /// Number of passes without better solution
  int numberBadPasses_;
  // 0 - fine, 1 can't be better, 2 max node
  int solveState_;
};

#endif

/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
*/
