#include <LINK/algorithm/Partitioning.h>
#include <LINK/graph/Attribute.h>
#include <LINK/graph/Vertex.h>
#include <LINK/graph/Graph.h>
#include <LINK/graph/Edge.h>
#include <LINK/basic/Set.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//#include <sys/time.h>		commented out for portability
//#include <sys/resource.h>
/***********************************************/
/************  log elapsed time  ***************/
/***********************************************/
/*  commented out for portability reasons
static struct rusage orusage ;
double log_time() {  
   struct rusage rusage ;
   double etime1,etime2, ttime ;
   getrusage(RUSAGE_SELF,&rusage) ;
   etime1 = (rusage.ru_utime.tv_sec - orusage.ru_utime.tv_sec) +
            (rusage.ru_utime.tv_usec - orusage.ru_utime.tv_usec) / 1000000.0 ;
   etime2 = (rusage.ru_stime.tv_sec - orusage.ru_stime.tv_sec) +
            (rusage.ru_stime.tv_usec - orusage.ru_stime.tv_usec) / 1000000.0 ;
   ttime = etime1+etime2;
   getrusage(RUSAGE_SELF,&orusage);
   return(ttime);
}
*/
void initCells(Graph *g, VertexInfo *cells)
{
	int i, c, num_v = g->order();
	Vertex **vertices = g->vertexStart();
	for (i=0; i<num_v; i++) {
		cells[i].node_num = i;
		cells[i].v = vertices[i];
		getAttribute((GraphObject*)vertices[i], "cost", c);
		cells[i].cost = c; 
		setAttribute(go(vertices[i]), "v_info", &cells[i]);
	}
}
long state1[32] = {
               3,
               0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342,
               0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
               0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86,
               0xda672e2a, 0x1588ca88, 0xe369735d, 0x904f35f7,
               0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
               0xde3b81e0, 0xdf0a6fb5, 0xf103bc02, 0x48f340fb,
               0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b,
               0xf5ad9d0e, 0x8999220b, 0x27fb47b9
               };
void randomizeVertices(VertexInfoPtr cells, int order)
{
	int i;
	for (i=0; i<order; i++) {
		if (Link_randomDouble0_1() < 0.5)
			cells[i].loc = 0;
		else
			cells[i].loc = 1;
	}
}
void initNet(VertexInfoPtr cell, Edge *edge, int from_block)
{
	Vertex * vertex;
	VertexInfoPtr vptr;
	CutStatePtr cptr;
	int size;
	getAttribute(go(edge), "cutstate", cptr);
	size = edge->vertices()->size();
	if (((*cptr)[FREE][0] == 0) && ((*cptr)[FREE][1] == 0)) {
		Iterator<Vertex *> get_vert(edge->vertices());
		while (get_vert(vertex)) {
			getAttribute(go(vertex), "v_info", vptr);
			if (!vptr->lock) {
				if (vptr->loc == from_block)
					(*cptr)[FREE][from_block]++;
				else
					(*cptr)[FREE][!from_block]++;
			}
		}
	}
	if ((*cptr)[FREE][from_block] == 1)
		cell->cost--;
	if ((*cptr)[FREE][!from_block] == 0)
		cell->cost++;
}
void initNetInfo(Graph *g, BucketArray **Buckets, 
		 CutStatePtr cptr, VertexInfoPtr cells,
		 int& current_cost, int *part_sizes)
{
	int i, num_nets = g->size(),
	    num_vertices = g->order();
	int from_block;
	Edge* edge;
	Set<Edge*> incident_edges;
	ContainerNode *cn;
	part_sizes[0] = part_sizes[1] = 0;
	for (i=0; i<num_vertices; i++) {
		cells[i].lock = 0;
		cells[i].cost = 0;
	}
	for (i=0; i<num_nets; i++) {
		cptr[i][FREE][0] = cptr[i][FREE][1] = 0;
		cptr[i][LOCKED][0] = cptr[i][LOCKED][1] = 0;
	}
	for (i=0; i<num_vertices; i++) {
		from_block = cells[i].loc;
		part_sizes[from_block]++;
		incident_edges = cells[i].v->incidentEdges();
		Iterator<Edge *> get_edge(&incident_edges);
		while (get_edge(edge)) {
			initNet(&cells[i], edge, from_block);
		}
		cn=Buckets[cells[i].loc]->insert(cells[i].cost,&cells[i]);
		cells[i].lp = cn;
	}
	current_cost = 0;
	for (i=0; i<num_nets; i++) {
		if (cptr[i][FREE][from_block]>0&&cptr[i][FREE][!from_block]>0)
			current_cost++;
	}
}
void printCells(VertexInfoPtr Cells, int num_vertices)
{
	int i;
	for (i=0; i<num_vertices; i++)
		cout << i << ":" << Cells[i].loc << endl;
		cout << "---------------------------" << endl;
}
void printCutstate(CutStatePtr cutstate, int num_nets)
{
	int i;
	for (i=0; i<num_nets; i++)
		cout << "{{" << cutstate[i][0][0] << ","
		<< cutstate[i][0][1] << "}, {"
		<< cutstate[i][1][0] <<  ","
		<< cutstate[i][1][1] << "}}" << endl;
	cout << "---------------------------" << endl;
}
