#pragma warning (disable:4786) 

#include <vector>

struct sort_set{
	int m_index;
	double m_value;
	std::vector<double> m_aryParamters;
};

struct model_input {
	std::vector<double> m_aryTestParameters;				// default parameter for creating true data for test
	std::vector<int> m_aryLocationOfOptParameter;			// index of optimized parameter
	std::vector<std::string> m_aryDate;						// time 
	std::vector< std::vector<double> > m_aryInputData;		// input data [record num.][input data index]
	std::vector< std::vector<double> > m_aryObsData;		// observed data
};

class CSCE_UA
{
	// M.Ueyama (2014.06.16)
public:
	CSCE_UA(double m_dErrorValue);

	// parameters for conducting SCE-UA	
	int m_maxn;				// 終了条件として目的関数計算回数の上限
	int m_kstop;			// m_dEpsPercent 基準で終了する最低限の混ぜ合わせ回数
	double m_dEpsPercent;	// 終了基準の目的関数結果変化率
	int m_ngs;				// コンプレックスグループ数
	int m_nopt;				// 同定パラメータの数
	
	int m_npg;				// 各コンプレックスグループ内での候補値数	 (2以上、基本設定は NPG = 3 * 同定パラメタ数 + 1)
	int m_nps;				// サブコンプレックス作業での候補値数 (NSP = 同定パラメタ数 + 1)
	int m_nspl;				// 各コンプレックスグループ内での候補値が進化する回数　(基本設定はNSPL = NPG)
	int m_mings;			// コンプレックスグループ数の最低値 (基本設定はMINGS = NGS)
	int m_iniflg;			// 3行目以降のパラメタ初期値入力選択　(0は初期値利用しない、1は初期値利用)
	int m_iprint;			// 最適化計算結果のプリントオプション (0は各混ぜ合わせの後順位1のみ出力、1はすべての候補値の結果を出力)

	int m_npar;				// モデルのパラメタ数
	int m_ndata;			// 目的関数計算で利用される観測流量データの数
	int m_iobj;				// 目的関数の選択 (1: SLS, 2: HMLE, 3:NSE, 4: RMSE)
	int m_idata;			// 観測データの活用選択 (0: 観測データを使用、 1: 設定パラメタを用いて合成データを作成し観測値とする)

	int m_iRecordNum;		// 観測データの数

	int m_iseed;
	double m_dErrorValue;	// クラス使用環境下における異常値

	int m_iOptimizedPrm;	// 最適化する項目番号

	std::vector<double> m_aryIniPrm;			// array for initial value of target paramameter
	std::vector<double> m_aryLowPrm;			// array for lower boudary of parameter space
	std::vector<double> m_aryHighPrm;			// array for upper boudary of parameter space
	std::vector<double> m_aryLowPrmDefault;		// array for lower boudary of parameter space
	std::vector<double> m_aryHighPrmDefault;	// array for upper boudary of parameter space
	std::vector<double> m_aryBestPrm;			// array for best parameter space
	double m_dBestFunc;

	std::vector<int> m_jseed;

	void create_random_seed_defualt(int nrun, bool bUseTime = false);
	void set_default_sce_parameters(int nopt, int ngs);
	bool sceua(model_input& cModel, const char strOutFile[], int iCurrentNumber, 
		void (*model_func) (std::vector<double>& , const std::vector< std::vector<double> >& ,  std::vector< std::vector<double> >&) );

	
private:
	void cce(std::vector< std::vector<double> >& s, std::vector<double>& sf, 
		 std::vector<double>& xnstd, int icall, int iseed, model_input& cModel, 
		 void (*model_func) (std::vector<double>& , const std::vector< std::vector<double> >& ,  std::vector< std::vector<double> >&));
	double functn(const int& nopt, const int& npar, const int& iobj,
			  std::vector< std::vector<double> >& obsq, std::vector<double>& x, std::vector< std::vector<double> >& p, std::vector<double>& pt, std::vector<int>& loc,
			  void (*model_func) (std::vector<double>& , const std::vector< std::vector<double> >& ,  std::vector< std::vector<double> >&) );
	double max(double iA, double iB);
	double min(double iA, double iB);
	double rand_normal();
	double rand_Gaussian_dev(int&);
	void chkcst(int , double& , double& , double& , int& );
	void chkcst(int nopt, std::vector<double>& x, std::vector<double>& bl, std::vector<double>& bu, int& ibound);
	void sort_sce(int , int , std::vector< std::vector<double> >& , std::vector<double>& );
	void sort_sce(int , std::vector<int>& );
	static bool compare(const sort_set &s1, const sort_set &s2) ;
	void get_point(int& , int , int& , std::vector<double>& , std::vector<double>& , std::vector<double>& , std::vector<double>& ,std:: vector<double>& );
	void parstt(int , int , std::vector< std::vector<double> >& , std::vector<double>& , std::vector<double>& , double& , int& );
	void comp(int , int , int , int , int , std::vector< std::vector<double> >& , std::vector<double>& , std::vector< std::vector<double> >& , std::vector<double>& );
};