/* -------------------------------------------------------------

This file is a component of SDPA
Copyright (C) 2004-2020 SDPA Project

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

------------------------------------------------------------- */
/*--------------------------------------------------
  sdpa_call.h
--------------------------------------------------*/

/***************************************************
   In this header file,
   Do NOT use 'using namespace sdpa;'.
   Otherwise, if users define their OWN 'sdpa' namespace,
   it would be trouble.
***************************************************/


#ifndef __sdpa_call_h__
#define __sdpa_call_h__

#include <sdpa_right.h>
#include <sdpa_newton.h>
#include <sdpa_chordal.h>
#include <sdpa_parts.h>
#include <sdpa_struct.h>  
#include <cstdio>
#include <vector>
#include <algorithm>  

/*  The class list is generated by the following command
  $ grep class *.h | grep -v \; | grep -v SDPA | tr ':' ' ' | \
    awk '{print $2 " " $3 ";"}' 
*/

namespace sdpa {
  class BlockStruct;
  class Chordal;
  class Solutions;
  class InputData;
  class Residuals;
  class WorkVariables;
  class IO;
  class Jal;
  class Lal;
  class Newton;
  class ComputeTime;
  class Parameter;
  class StepLength;
  class DirectionParameter;
  class Switch;
  class AverageComplementarity;
  class RatioInitResCurrentRes;
  class SolveInfo;
  class Phase;
  class Vector;
  class BlockVector;
  class SparseMatrix;
  class DenseMatrix;
  class SparseLinearSpace;
  class DenseLinearSpace;
  class Time;

  // internal class of SDPA
  class IndexLIJv
  {
  public:
    int l,i,j;
    double value;
    IndexLIJv();
    ~IndexLIJv();
    static bool compare(IndexLIJv* a, IndexLIJv* b);
  };
};


class SDPA
{
public:

  enum PhaseType {noINFO, pFEAS,dFEAS,pdFEAS,pdINF,
		  pFEAS_dINF,pINF_dFEAS,pdOPT,pUNBD,dUNBD};
  enum ParameterType {PARAMETER_DEFAULT,
                      PARAMETER_UNSTABLE_BUT_FAST,
                      PARAMETER_STABLE_BUT_SLOW};
  
  enum ConeType {SDP, SOCP, LP};
  // SOCP is not implemented in the current version.
  
  enum SparseType {AUTO, SPARSE, DENSE};
  // when AUTO is set, the type is analyzed by the file extenstion.

  SDPA();
  ~SDPA();

  void setParameterType(ParameterType type = PARAMETER_DEFAULT);
  void setParameterMaxIteration(int maxIteration);
  void setParameterEpsilonStar (double epsilonStar);
  void setParameterLambdaStar  (double lambdaStar);
  void setParameterOmegaStar   (double omegaStar);
  void setParameterLowerBound  (double lowerBound);
  void setParameterUpperBound  (double upperBound);
  void setParameterBetaStar    (double betaStar);
  void setParameterBetaBar     (double betaBar);
  void setParameterGammaStar   (double gammaStar);
  void setParameterEpsilonDash (double epsilonDash);

  void setParameterPrintXVec(char* xPrint);
  void setParameterPrintXMat(char* XPrint);
  void setParameterPrintYMat(char* YPrint);
  void setParameterPrintInformation(char* infPrint);

  void setDisplay(FILE* Display  = stdout);
  void setResultFile(FILE* fpout = stdout);
  void setInitPoint(bool isInitPoint);

  void setNumThreads(int NumThreads=0);

  ParameterType getParameterType();
  int    getParameterMaxIteration();
  double getParameterEpsilonStar ();
  double getParameterLambdaStar  ();
  double getParameterOmegaStar   ();
  double getParameterLowerBound  ();
  double getParameterUpperBound  ();
  double getParameterBetaStar    ();
  double getParameterBetaBar     ();
  double getParameterGammaStar   ();
  double getParameterEpsilonDash ();

  char* getParameterPrintXVec();
  char* getParameterPrintXMat();
  char* getParameterPrintYMat();
  char* getParameterPrintInformation();

  FILE* getDisplay();
  FILE* getResultFile();
  bool getInitPoint();
  
  int getNumThreads();
  
  void inputConstraintNumber(int m);
  void inputBlockNumber(int nBlock);
  void inputBlockSize(int l, int size);
  void inputBlockType(int l, ConeType coneType);
  void inputCVec(int k, double value);
  void inputElement(int k, int l, int i, int j, double value,
		    bool inputCheck = false);
  void inputInitXVec(int k, double value);
  void inputInitXMat(int l, int i, int j, double value);
  void inputInitYMat(int l, int i, int j, double value);

  void initializeUpperTriangleSpace();
  void initializeUpperTriangle(bool inputTwiceCheck = false);
  void initializeSolve();
  void resetParameters();
  
  void solve();

  double* getResultXVec();
  double* getResultXMat(int l);
  double* getResultYMat(int l);
  double getPrimalObj();
  double getDualObj();
  double getPrimalError();
  double getDualError();
  double getDigits();
  int    getIteration();
  double getMu();
  double getDualityGap();
  PhaseType getPhaseValue();
  void   getPhaseString(char* str);
  double getSolveTime();

  int      getConstraintNumber();
  int      getBlockNumber();
  int      getBlockSize(int l);
  ConeType getBlockType(int l);
  
  void getDimacsError(double* DimacsError);
  void printDimacsError(double* DimacsError, char* printFormat,
			FILE* fp = stdout);
  
  void printResultXVec(FILE* fp = stdout);
  void printResultXMat(FILE* fp = stdout);
  void printResultYMat(FILE* fp = stdout);
  void printComputationTime(FILE* fp = stdout);
  void printParameters(FILE* fp = stdout);
  static void printSDPAVersion(FILE* fp = stdout);

  void readInput(char* filename, FILE* fpout = NULL,
		 SparseType type = AUTO);
  void readInit(char* filename, FILE* fpout = NULL,
		SparseType type = AUTO);
  void readParameter(char* filename, FILE* fpout = NULL);
  void writeInputSparse(char* filename, char* printFormat);
  void writeInitSparse(char* filename, char* printFormat);
  
  void terminate();
  void copyCurrentToInit();

  // setKappa is for only SDPA developers
  void setKappa(double KAPPA);

  // // for debugging, private is replaced by public
  // public:
private:
  double KAPPA;
  int  m;
  int  nBlock;
  FILE* Display;
  FILE* fpout;
  bool isInitPoint;
  ParameterType typeParameter;

  int pIteration;

  sdpa::ComputeTime            com;
  sdpa::Parameter              param;
  sdpa::BlockStruct            bs;
  sdpa::InputData              inputData;
  sdpa::Newton                 newton;
  sdpa::Chordal                chordal;
  sdpa::Solutions              currentPt;
  sdpa::WorkVariables          work;
  sdpa::DenseLinearSpace       initPt_xMat;
  sdpa::DenseLinearSpace       initPt_zMat;
  sdpa::Residuals              initRes;
  sdpa::Residuals              currentRes;
  sdpa::StepLength             alpha;
  sdpa::DirectionParameter     beta;
  sdpa::Switch                 reduction;
  sdpa::AverageComplementarity mu;
  sdpa::RatioInitResCurrentRes theta;
  sdpa::SolveInfo              solveInfo;
  sdpa::Phase                  phase;


  // temporary space to store
  // upper trianguler part non-zeros.
  vector<sdpa::IndexLIJv*> * NonZeroElements;
  void printNonZeroElements(FILE* fpout = stdout);
  void sortNonZeroElements();
  void checkNonZeroElements();
  void setNonZeroBlockStruct();
  void setNonZeroElements();

  void writeSparseLinearSpace(FILE* fp, char* printFormat,
			      sdpa::SparseLinearSpace& A, int k);
  void writeDenseLinearSpace(FILE* fp, char* printFormat,
			     sdpa::DenseLinearSpace& X, int k);

};

#endif // __sdpa_call_h__
