/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                       */
/*    This file is part of the HiGHS linear optimization suite           */
/*                                                                       */
/*    Available as open-source under the MIT License                     */
/*                                                                       */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**@file lp_data/HighsIis.h
 * @brief Class-independent utilities for HiGHS
 */
#ifndef LP_DATA_HIGHSIIS_H_
#define LP_DATA_HIGHSIIS_H_

#include "model/HighsModel.h"

const bool kIisDevReport = false;

enum IisBoundStatus : int {
  kIisBoundStatusDropped = -1,
  kIisBoundStatusNull,   // 0
  kIisBoundStatusFree,   // 1
  kIisBoundStatusLower,  // 2
  kIisBoundStatusUpper,  // 3
  kIisBoundStatusBoxed   // 4
};

enum IisModelStatus {
  kIisModelStatusFeasible = -1,
  kIisModelStatusUnknown,     // 0
  kIisModelStatusInfeasible,  // 1
  kIisModelStatusReducible,   // 2
  kIisModelStatusIrreducible  // 3
};

struct HighsIisInfo {
  double simplex_time = 0;
  HighsInt simplex_iterations = 0;
};

class HighsIis {
 public:
  HighsIis() {}

  void clear();
  void invalid(const HighsLp& lp);
  std::string iisBoundStatusToString(HighsInt bound_status) const;
  void report(const std::string& message, const HighsLp& lp) const;
  void addCol(const HighsInt col, const HighsInt status = kIisBoundStatusNull);
  void addRow(const HighsInt row, const HighsInt status = kIisBoundStatusNull);
  void removeCol(const HighsInt col);
  void removeRow(const HighsInt row);
  HighsStatus deduce(const HighsLp& lp, const HighsOptions& options,
                     const HighsBasis& basis);
  void setLp(const HighsLp& lp);
  HighsInt nonIsStatus() const;
  void setStatus(const HighsLp& lp);

  HighsStatus compute(const HighsLp& lp, const HighsOptions& options,
                      const HighsBasis* basis = nullptr);

  bool trivial(const HighsLp& lp, const HighsOptions& options);
  bool rowValueBounds(const HighsLp& lp, const HighsOptions& options);

  bool indexStatusOkReturn(const bool return_value) const {
    return return_value;
  }
  bool lpDataOkReturn(const bool return_value) const { return return_value; }
  bool lpOkReturn(const bool return_value) const { return return_value; }

  bool indexStatusOk(const HighsLp& lp) const;
  bool lpDataOk(const HighsLp& lp, const HighsOptions& options) const;
  bool lpOk(const HighsOptions& options) const;

  // Data members
  bool valid_ = false;
  HighsInt status_;
  HighsInt strategy_ = kIisStrategyMin;
  std::vector<HighsInt> col_index_;
  std::vector<HighsInt> row_index_;
  std::vector<HighsInt> col_bound_;
  std::vector<HighsInt> row_bound_;
  std::vector<HighsInt> col_status_;
  std::vector<HighsInt> row_status_;
  std::vector<HighsIisInfo> info_;
  HighsModel model_;
};

#endif  // LP_DATA_HIGHSIIS_H_
