//*	A SHORT VERSION
int main(int argc, char ** argv)
{
    // s_InputFile = baseDir + <name of the input file>
    string s_InputFile; //path of the input file. PICK A SYMMETRIC MATRIX!!!
    s_InputFile = baseDir;
    s_InputFile += DIR_SEPARATOR;
    s_InputFile += "Graphs";
    s_InputFile += DIR_SEPARATOR;
    s_InputFile += "mtx-spear-head.mtx";

    //Generate and color the graph
    GraphColoringInterface * g = new GraphColoringInterface(SRC_FILE, s_InputFile.c_str(), "AUTO_DETECTED");

    //Color the bipartite graph with the specified ordering
    g->Coloring("LARGEST_FIRST", "DISTANCE_TWO");

    /*Done with coloring. Below are possible things that you may
    want to do after coloring:
    //*/

    /* 1. Check DISTANCE_TWO coloring result
    cout<<"Check DISTANCE_TWO coloring result"<<endl;
    g->CheckDistanceTwoColoring();
    Pause();
    //*/

    //* 2. Print coloring results
    g->PrintVertexColoringMetrics();
    Pause();
    //*/

    //* 3. Get the list of colorID of vertices
    vector<int> vi_VertexColors;
    g->GetVertexColors(vi_VertexColors);

    //Display vector of VertexColors
    printf("vector of VertexColors (size %d) \n", (int)vi_VertexColors.size());
    displayVector(&vi_VertexColors[0], vi_VertexColors.size(), 1);
    Pause();
    //*/

    /* 4. Get seed matrix
    int i_SeedRowCount = 0;
    int i_SeedColumnCount = 0;
    double** Seed = g->GetSeedMatrix(&i_SeedRowCount, &i_SeedColumnCount);

    //Display Seed
    printf("Seed matrix %d x %d \n", i_SeedRowCount, i_SeedColumnCount);
    displayMatrix(Seed, i_SeedRowCount, i_SeedColumnCount, 1);
    Pause();
    //*/

    delete g;
    return 0;
}
int main()
{
	// s_InputFile = baseDir + <name of the input file>
	string s_InputFile; //path of the input file
	s_InputFile = baseDir + "mtx-spear-head.mtx"; 

	// Step 1: Determine sparsity structure of the Jacobian.
	// This step is done by an AD tool. For the purpose of illustration here, we read the structure from a file, 
	// and store the structure in a Compressed Row Format. 
	unsigned int *** uip3_SparsityPattern = new unsigned int **;
	double*** dp3_Value = new double**;
	int rowCount, columnCount;
	ConvertGeneralMatrixMarketFormatToCompressedSparseRowFormat(s_InputFile, uip3_SparsityPattern, dp3_Value,rowCount, columnCount);

	cout<<"just for debugging purpose, display the 2 matrices: the matrix with SparsityPattern only and the matrix with Value"<<endl;
	cout<<fixed<<showpoint<<setprecision(2);
	cout<<"(*uip3_SparsityPattern)"<<endl;
	displayCompressedRowMatrix((*uip3_SparsityPattern),rowCount);
	cout<<"(*dp3_Value)"<<endl;
	displayCompressedRowMatrix((*dp3_Value),rowCount);
	cout<<"Finish ReadMatrixMarketAdjacencyGraph2CompressedSparseRowFormat()"<<endl;
	Pause();

	//Step 2: Obtain the seed matrix via coloring.
	double*** dp3_Seed = new double**;
	int *ip1_SeedRowCount = new int;
	int *ip1_SeedColumnCount = new int;
	int* ip1_ColorCount = new int; //The number of distinct colors used to color the graph
	GraphColoringInterface *g = new GraphColoringInterface;

	//Step 2.1: Read the sparsity pattern of the given Hessian matrix (compressed sparse rows format)
	//and create the corresponding graph
	g->BuildGraph_ADOLC(*uip3_SparsityPattern, rowCount);

	//Step 2.2: Color the bipartite graph with the specified ordering
	g->Coloring("ACYCLIC_FOR_INDIRECT_RECOVERY", "SMALLEST_LAST");

	//Step 2.3 (Option 1): From the coloring information, create and return the seed matrix
	*dp3_Seed = g->GetSeedMatrix(ip1_SeedRowCount, ip1_SeedColumnCount);
	/* Notes:
	Step 2.3 (Option 2): From the coloring information, you can also get the vector of colorIDs of vertices
		vector<int> vi_VertexColors;
		g->GetVertexColors(vi_VertexColors);

	In stead of doing step 2.1-2.3 (Option 1), you can just call the bellow function:
		g->GenerateSeedHessian(*uip3_SparsityPattern, rowCount, dp3_Seed, ip1_SeedRowCount, ip1_SeedColumnCount, "ACYCLIC", "SMALLEST_LAST"); // this function is inside GraphColoringInterface class
	*/
	cout<<"Finish GenerateSeed()"<<endl;
	*ip1_ColorCount = *ip1_SeedColumnCount;

	displayMatrix(*dp3_Seed, *ip1_SeedRowCount, *ip1_SeedColumnCount);
	Pause();

	// Step 3: Obtain the Hessian-seed matrix product.
	// This step will also be done by an AD tool. For the purpose of illustration here, the orginial matrix V 
	// (for Values) is multiplied with the seed matrix S. The resulting matrix is stored in dp3_CompressedMatrix.
	double*** dp3_CompressedMatrix = new double**;
	cout<<"Start MatrixMultiplication()"<<endl;
	MatrixMultiplication_VxS(*uip3_SparsityPattern, *dp3_Value, rowCount, columnCount, *dp3_Seed, *ip1_SeedColumnCount, dp3_CompressedMatrix);
	cout<<"Finish MatrixMultiplication()"<<endl;

	displayMatrix(*dp3_CompressedMatrix,rowCount,*ip1_ColorCount);
	Pause();

	//Step 4: Recover the numerical values of the original matrix from the compressed representation. 
	// The new values are store in "dp3_NewValue"
	double*** dp3_NewValue = new double**;
	HessianRecovery::IndirectRecover_ADOLCFormat(g, *dp3_CompressedMatrix, *uip3_SparsityPattern, dp3_NewValue);
	cout<<"Finish Recover()"<<endl;

	displayCompressedRowMatrix(*dp3_NewValue,rowCount);
	Pause();

	//Check for consistency, make sure the values in the 2 matrices are the same.
	if (CompressedRowMatricesREqual(*dp3_Value, *dp3_NewValue, rowCount,0,1)) cout<< "*dp3_Value == dp3_NewValue"<<endl;
	else cout<< "*dp3_Value != dp3_NewValue"<<endl;

	Pause();
	return 0;
}
void CProbingSampler::precompute()
{
	SG_DEBUG("Entering\n");

	// if already precomputed, nothing to do
	if (m_is_precomputed)
	{
		SG_DEBUG("Coloring vector already computed! Exiting!\n");
		return;
	}

	// do coloring things here and save the coloring vector
	SparsityStructure* sp_str=m_matrix_operator->get_sparsity_structure(m_power);

	GraphColoringInterface* Color
		=new GraphColoringInterface(SRC_MEM_ADOLC, sp_str->m_ptr, sp_str->m_num_rows);

	std::string str_ordering;
	switch(m_ordering)
	{
	case NATURAL:
		str_ordering="NATURAL";
		break;
	case LARGEST_FIRST:
		str_ordering="LARGEST_FIRST";
		break;
	case DYNAMIC_LARGEST_FIRST:
		str_ordering="DYNAMIC_LARGEST_FIRST";
		break;
	case DISTANCE_TWO_LARGEST_FIRST:
		str_ordering="DISTANCE_TWO_LARGEST_FIRST";
		break;
	case SMALLEST_LAST:
		str_ordering="SMALLEST_LAST";
		break;
	case DISTANCE_TWO_SMALLEST_LAST:
		str_ordering="DISTANCE_TWO_SMALLEST_LAST";
		break;
	case INCIDENCE_DEGREE:
		str_ordering="INCIDENCE_DEGREE";
		break;
	case DISTANCE_TWO_INCIDENCE_DEGREE:
		str_ordering="DISTANCE_TWO_INCIDENCE_DEGREE";
		break;
	case RANDOM:
		str_ordering="RANDOM";
		break;
	}

	std::string str_coloring;
	switch(m_coloring)
	{
	case DISTANCE_ONE:
		str_coloring="DISTANCE_ONE";
		break;
	case ACYCLIC:
		str_coloring="ACYCLIC";
		break;
	case ACYCLIC_FOR_INDIRECT_RECOVERY:
		str_coloring="ACYCLIC_FOR_INDIRECT_RECOVERY";
		break;
	case STAR:
		str_coloring="STAR";
		break;
	case RESTRICTED_STAR:
		str_coloring="RESTRICTED_STAR";
		break;
	case DISTANCE_TWO:
		str_coloring="DISTANCE_TWO";
		break;
	}

	Color->Coloring(str_ordering, str_coloring);

	std::vector<int32_t> vi_VertexColors;
	Color->GetVertexColors(vi_VertexColors);

	REQUIRE(vi_VertexColors.size()==static_cast<uint32_t>(m_dimension),
		"dimension mismatch, %d vs %d!\n", vi_VertexColors.size(), m_dimension);

	m_coloring_vector=SGVector<int32_t>(vi_VertexColors.size());

	for (std::vector<int32_t>::iterator it=vi_VertexColors.begin();
		it!=vi_VertexColors.end(); it++)
	{
		index_t i=static_cast<index_t>(std::distance(vi_VertexColors.begin(), it));
		m_coloring_vector[i]=*it;
	}

	Map<VectorXi> colors(m_coloring_vector.vector, m_coloring_vector.vlen);
	m_num_samples=colors.maxCoeff()+1;
	SG_DEBUG("Using %d samples (aka colours) for probing trace sampler\n",
			m_num_samples);

	delete sp_str;
	delete Color;

	// set the precomputed flag true
	m_is_precomputed=true;

	SG_DEBUG("Leaving\n");
}
int main()
{
	double*** dp3_Seed = new double**;
	int *ip1_SeedRowCount = new int;
	int *ip1_SeedColumnCount = new int;
	int i_RowCount, i_MaxNonZerosInRows;

	//populate the Hessian. Uncomment one of the 2 matrices below

	/* 1x1 matrix
	i_RowCount = 1;
	i_MaxNonZerosInRows = 1;
	unsigned int **uip2_HessianSparsityPattern = new unsigned int *[i_RowCount];//[1][1]
	for(int i=0;i<1;i++) uip2_HessianSparsityPattern[i] = new unsigned int[i_MaxNonZerosInRows + 1];
	uip2_HessianSparsityPattern[0][0] = 1;		uip2_HessianSparsityPattern[0][1] = 0;
	//*/

	//* 5x5 matrix
	i_RowCount = 5;
	i_MaxNonZerosInRows = 2;
	unsigned int **uip2_HessianSparsityPattern = new unsigned int *[i_RowCount];//[5][5]
	for(int i=0;i<5;i++) uip2_HessianSparsityPattern[i] = new unsigned int[i_MaxNonZerosInRows + 1];
	uip2_HessianSparsityPattern[0][0] = 1;		uip2_HessianSparsityPattern[0][1] = 1;
	uip2_HessianSparsityPattern[1][0] = 2;		uip2_HessianSparsityPattern[1][1] = 0;		uip2_HessianSparsityPattern[1][2] = 2;
	uip2_HessianSparsityPattern[2][0] = 2;		uip2_HessianSparsityPattern[2][1] = 1;		uip2_HessianSparsityPattern[2][2] = 3;
	uip2_HessianSparsityPattern[3][0] = 2;		uip2_HessianSparsityPattern[3][1] = 2;		uip2_HessianSparsityPattern[3][2] = 4;
	uip2_HessianSparsityPattern[4][0] = 1;		uip2_HessianSparsityPattern[4][1] = 3;
	//*/


	//Step 1: Read the sparsity pattern of the given Hessian matrix (compressed sparse rows format)
	//and create the corresponding graph
	GraphColoringInterface * g = new GraphColoringInterface(SRC_MEM_ADOLC, uip2_HessianSparsityPattern, i_RowCount);

	//Step 2: Color the bipartite graph with the specified ordering
	g->Coloring("SMALLEST_LAST", "STAR");

	//Step 3: From the coloring information, create and return the seed matrix
	(*dp3_Seed) = g->GetSeedMatrix(ip1_SeedRowCount, ip1_SeedColumnCount);
	/* Notes:
	In stead of doing step 1-3, you can just call the bellow function:
		g->GenerateSeedHessian(uip2_HessianSparsityPattern, i_RowCount, dp3_Seed, ip1_SeedRowCount, ip1_SeedColumnCount, "STAR", "SMALLEST_LAST"); // this function is inside GraphColoringInterface class
	*/
	cout<<"Finish GenerateSeed()"<<endl;

	//this SECTION is just for displaying the result
	g->PrintGraphStructure();
	g->PrintVertexColors();
	g->PrintVertexColoringMetrics();
	double **Seed = *dp3_Seed;
	int rows = g->GetVertexCount();
	int cols = g->GetVertexColorCount();
	cout<<"Seed matrix: ("<<rows<<","<<cols<<")"<<endl;
	for(int i=0; i<rows; i++) {
		for(int j=0; j<cols; j++) {
			cout<<setw(6)<<Seed[i][j];
		}
		cout<<endl;
	}
	//END SECTION

	//GraphColoringInterface * g = new GraphColoringInterface();
	delete g;
	g = NULL;

	//double*** dp3_Seed = new double**;
	delete dp3_Seed;
	dp3_Seed = NULL;
	Seed = NULL;

	//int *ip1_SeedRowCount = new int;
	delete ip1_SeedRowCount;
	ip1_SeedRowCount = NULL;

	//int *ip1_SeedColumnCount = new int;
	delete ip1_SeedColumnCount;
	ip1_SeedColumnCount = NULL;

	//unsigned int **uip2_HessianSparsityPattern = new unsigned int *[i_RowCount];//[5][5]
	free_2DMatrix(uip2_HessianSparsityPattern, i_RowCount);
	uip2_HessianSparsityPattern = NULL;

	return 0;
}