//
//  Tensor Regression.h
//  Tensor Regression
//
//  Created by Bui  Thang on 7/30/13.
//  Copyright (c) 2013 __MyCompanyName__. All rights reserved.
//

#ifndef Tensor_Regression_Tensor_Regression_h
#define Tensor_Regression_Tensor_Regression_h
using namespace std;
extern int N;
extern double lambda;// coefficient of regularization term
extern int n;// The length of siRNA sequence
extern int K;// the Number of Rules
class Vector;
class EncodingMatrix{
	bool X[25][5];
	double label;
public:
    EncodingMatrix();
  //  ~EncodingMatrix(){}
    void Get(bool EM[25][5]);
    void Input(string s);
    int Getelement(int,int);
    void Output();
};
extern EncodingMatrix C1[2600],C2[2600],C3[2600],C4[2600], ScoreData[3000];
void readfile(string filename);
class Trans_Matrix{
	double **T;
public:
    Trans_Matrix();
    Trans_Matrix(Trans_Matrix &X);
    ~Trans_Matrix(){for (int i=1;i<=4;i++) delete [] T[i];}
    
   // void Delete(){delete [] T;}
    void Initialize(Trans_Matrix Rule);
    void Intialize1();
    void Set(double a[5][25]);
    double Getelement(int i,int j);
    void Update(double v[],int pos);
    bool RuleConstraint(double v[],int pos);
    void Show();
    Trans_Matrix &operator=(const Trans_Matrix &MT);
    friend void RuleRead(string rulefile, Trans_Matrix Rules[]);
    friend double BComp(Trans_Matrix TM,int p, int q);
    double FrobeniusNorm();
    Trans_Matrix operator-(const Trans_Matrix &MT);
};
// Display elements in a matrix of size n*m
void MatrixDisp(long A[25][25], int,int);
// S matrix contains value of S(p,q)
void VectorDisp(double[],int);
class Tensor{
    double **Arr;
    int p,q;// size of a tensor
    double score;
    double *Prop;
    int Pn;
public:
    Tensor();
    Tensor(const Tensor&);
    ~Tensor(){
        for (int i=1;i<=p;i++)delete[] Arr[i];
        delete [] Prop;
    }
    // transform a siRNA sequence with its score to a tensor
    void Set(double, string,Trans_Matrix[]);
    // transform siRNA sequences in Data set to tensor array
    // Get a tensor
    void Get(double Matrix[][25],int&,int&);
    // Get value at position (i,j)
    double value(int,int)const;
    // Get efficacy score
    double GetScore()const;
    // Get x axis
    int Getx()const;
    // Get y axis
    int Gety()const;
    // Consider a array as tensor;
    void Input(double **Matrix,int n, int m);
    // add a constant to a matrix
    Tensor operator+(double scale)const;
    void operator+=(const double scale);
    //Tensor operator+(const Tensor y);
    void operator+=(const Tensor &y);
    friend Tensor operator+(const Tensor &x, const Tensor &y);
    Tensor &operator=(const Tensor &y);
    Tensor operator=(const double a);
    Tensor operator*(double scale)const;
    Tensor Inverse()const;
    Vector GetP();
    double ProbeniusNorm();
    friend ostream &operator<<(ostream &out,const Tensor);
};
void TensorData(string rulefile, Trans_Matrix TM[],Tensor Dataset[],int &N,char sign);
extern Tensor TensorArray[];// contains tensors of siRNA sequences.
//Display tensor data set
void Display(string, Trans_Matrix[]);
// Product of two vectors (mx1 times 1xm)
class Vector{
    double *v;//[150];
    int len;
    public:
    Vector();//Constructor
    Vector(const Vector&);
    ~Vector();
    void Initialize(int);
    void Set(double [],int);
    int length(){return len;}
    void Setlen(int a){ len=a;}
    void Get(double a[],int &size){size=len; for(int i=1;i<=len;i++) a[i]=v[i];}
    Tensor operator*(const Vector y);//product of 2 vectors (mx1 times 1xm)
    friend Vector operator*(const Tensor &y,const Vector &x);// Product of a tensor and vector
    friend Vector operator*(const Vector &x,const Tensor &y);// Product of vector and tensor
    // Scale vector with constant c;
    Vector operator*(double y) const;
    void Normalize();
    //Inner Product of 2 vectors;
    double InnerProduct(const Vector &y);
    Vector operator-(const Vector &y)const;// Subtraction of 2 vectors
     Vector operator+(const Vector &y)const;// Sum of 2 vectors
    void operator+=(const Vector &y);
   // void operator+=(const double y);
    void operator*=(const double a);
    void operator=(const Vector &y);// Assignment
    void operator=(const double a);
    double Norm2();// Norm L2
    void standlize();
  friend ostream &operator<<(ostream &out,const Vector);
    double operator[](int i){return v[i];}
};
// Tensor Regression predictor;
void TensorPredictor(int[],int,Vector&, Vector&,double[], double[]);
void Predictor(Tensor Testset[],int Ntest,Vector &alpha, Vector &beta, double Target[], double Pred[]);
// Correlation Coefficient of 2 vectors;
double Corr(double[],double[], int);
// Tensor Method
void Getdata(string input,string output,string, Trans_Matrix &R);
void Gettest(int indices[], int Test[], int &num, int k, int Train[],int &Trn);
void writetofile(Trans_Matrix T[]);
void Test(string testfile,char sign);
#endif
