00001
00024 #ifndef METISGRAPH_H_
00025 #define METISGRAPH_H_
00026 #include "MetisNode.h"
00027 #include "GMetisConfig.h"
00028 #include <vector>
00029 #include <iostream>
00030 using namespace std;
00031
00032 class MetisGraph{
00033 public:
00034 MetisGraph(){
00035 mincut =0;
00036 numEdges =0;
00037 numNodes = 0;
00038 boundaryNodes = NULL;
00039 coarseGraphMapTo = NULL;
00040 }
00041
00042 ~MetisGraph() {
00043 if(boundaryNodes != NULL){
00044 delete boundaryNodes;
00045 }
00046 }
00047
00048 void initMatches(){
00049
00050
00051
00052
00053
00054 matchFlag = new bool[numNodes];
00055 matches = new GNode[numNodes];
00056 arrayFill(matchFlag, numNodes, false);
00057
00058
00059
00060
00061 }
00062
00063 void releaseMatches(){
00064 delete[] matches;
00065 delete[] matchFlag;
00066 }
00067
00068 bool isMatched(int id){
00069 assert(id < numNodes);
00070
00071 return matchFlag[id];
00072 }
00073
00074 GNode getMatch(int id){
00075 assert(id < numNodes);
00076
00077 return matches[id];
00078 }
00079
00080 void initSubGraphMapTo(){
00081 subGraphMaps = new GNode[numNodes];
00082 }
00083
00084 GNode getSubGraphMapTo(int id){
00085 assert(id < numNodes);
00086 return subGraphMaps[id];
00087 }
00088
00089 void releaseSubGraphMapTo(){
00090 delete[] subGraphMaps;
00091 }
00092
00093 GNode getCoarseGraphMap(int id){
00094
00095 return coarseGraphMapTo[id];
00096 }
00097
00098 void releaseCoarseGraphMap(){
00099 if(coarseGraphMapTo!=NULL){
00100 delete[] coarseGraphMapTo;
00101 coarseGraphMapTo = NULL;
00102 }
00103 }
00104
00105 void initCoarseGraphMap(){
00106
00107 coarseGraphMapTo = new GNode[numNodes];
00108 }
00109
00110 void setMatch(int id, GNode node){
00111 assert(id < numNodes);
00112
00113
00114 matchFlag[id] = true;
00115 matches[id] = node;
00116 }
00117
00118 void setSubGraphMapTo(int id, GNode node){
00119 assert(id < numNodes);
00120 subGraphMaps[id] = node;
00121 }
00122
00123 void setCoarseGraphMap(int id, GNode node){
00124 assert(id < numNodes);
00125
00126 coarseGraphMapTo[id] = node;
00127 }
00128
00137 void incPartWeight(int index, int weight) {
00138 __sync_fetch_and_add(&partWeights[index], weight);
00139 }
00140
00144 void initPartWeight(size_t nparts) {
00145 if(partWeights.size() != nparts){
00146 partWeights.resize(nparts);
00147 for (size_t i = 0; i < partWeights.size(); ++i) {
00148 partWeights[i] = 0;
00149 }
00150 }
00151 }
00152
00158 void setPartWeight(int index, int weight) {
00159 partWeights[index]=weight;
00160 }
00161
00167 int getPartWeight(int part) {
00168 return partWeights[part];
00169 }
00170
00171
00175 void incNumEdges() {
00176 numEdges++;
00177 }
00178
00182 int getNumEdges() {
00183 return numEdges;
00184 }
00185
00186 void setNumEdges(int num) {
00187 numEdges = num;
00188 }
00189
00190 void setNumNodes(int num){
00191 numNodes = num;
00192 }
00193 int getNumNodes(){
00194 assert(numNodes > 0);
00195 return numNodes;
00196 }
00197
00201 void computeTwoWayPartitionParams() {
00202 partWeights.resize(2);
00203 partWeights[0] = 0;
00204 partWeights[1] = 0;
00205
00206 if(boundaryNodes == NULL){
00207 boundaryNodes = new GNodeSet(numNodes, &gNodeToInt);
00208 }else{
00209 unsetAllBoundaryNodes();
00210 }
00211 int mincut = 0;
00212 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00213 GNode node = *ii;
00214 MetisNode& nodeData = node.getData(Galois::NONE);
00215 int me = nodeData.getPartition();
00216 partWeights[me] += nodeData.getWeight();
00217 updateNodeEdAndId(node);
00218 if (nodeData.getEdegree() > 0 || graph->neighborsSize(node,Galois::NONE) == 0) {
00219 mincut += nodeData.getEdegree();
00220 setBoundaryNode(node);
00221 }
00222 }
00223 this->mincut =mincut / 2;
00224 }
00225
00229 int getMaxAdjSum() {
00230 int maxAdjSum = -1;
00231 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00232 GNode node = *ii;
00233 int adjwgtsum = node.getData(Galois::NONE).getAdjWgtSum();
00234 assert(adjwgtsum>=0||numEdges == 0);
00235 if (maxAdjSum < adjwgtsum) {
00236 maxAdjSum = adjwgtsum;
00237 }
00238 }
00239 return maxAdjSum;
00240 }
00241
00245 void computeKWayPartitionParams(int nparts) {
00246
00247 if(boundaryNodes == NULL){
00248 boundaryNodes = new GNodeSet(numNodes, &gNodeToInt);
00249 }else{
00250 unsetAllBoundaryNodes();
00251 }
00252 partWeights.resize(nparts);
00253 for (int i = 0; i < nparts; ++i) {
00254 partWeights[i] = 0;
00255 }
00256 int mincut = 0;
00257 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00258 GNode node = *ii;
00259 MetisNode& nodeData = node.getData(Galois::NONE);
00260 int me = nodeData.getPartition();
00261 partWeights[me] += nodeData.getWeight();
00262 updateNodeEdAndId(node);
00263 if (nodeData.getEdegree() > 0) {
00264 mincut += nodeData.getEdegree();
00265 int numEdges = graph->neighborsSize(node, Galois::NONE);
00266 nodeData.initPartEdAndIndex(numEdges);
00267
00268 for (GGraph::neighbor_iterator jj = graph->neighbor_begin(node, Galois::NONE), eejj = graph->neighbor_end(node, Galois::NONE); jj != eejj; ++jj) {
00269 GNode neighbor = *jj;
00270 MetisNode& neighborData = neighbor.getData(Galois::NONE);
00271 if (me != neighborData.getPartition()) {
00272 int edgeWeight = (int) graph->getEdgeData(node, jj, Galois::NONE);
00273 int k = 0;
00274 for (; k < nodeData.getNDegrees(); k++) {
00275 if (nodeData.getPartIndex()[k] == neighborData.getPartition()) {
00276 nodeData.getPartEd()[k] += edgeWeight;
00277 break;
00278 }
00279 }
00280 if (k == nodeData.getNDegrees()) {
00281 nodeData.getPartIndex()[nodeData.getNDegrees()] = neighborData.getPartition();
00282 nodeData.getPartEd()[nodeData.getNDegrees()] = edgeWeight;
00283 nodeData.setNDegrees(nodeData.getNDegrees() + 1);
00284 }
00285 }
00286
00287 }
00288 }
00289 if (nodeData.getEdegree() - nodeData.getIdegree() > 0) {
00290 setBoundaryNode(node);
00291 }
00292 }
00293 setMinCut(mincut / 2);
00294 }
00295
00296
00300 void updateNodeEdAndId(GNode node) {
00301 int ed = 0;
00302 int id = 0;
00303 MetisNode& nodeData = node.getData(Galois::NONE);
00304 for (GGraph::neighbor_iterator jj = graph->neighbor_begin(node, Galois::NONE), eejj = graph->neighbor_end(node, Galois::NONE); jj != eejj; ++jj) {
00305 GNode neighbor = *jj;
00306 int weight = (int) graph->getEdgeData(node, jj, Galois::NONE);
00307 if (nodeData.getPartition() != neighbor.getData(Galois::NONE).getPartition()) {
00308 ed = ed + weight;
00309 } else {
00310 id = id + weight;
00311 }
00312 }
00313 nodeData.setEdegree(ed);
00314 nodeData.setIdegree(id);
00315 }
00316
00320 GGraph* getGraph() {
00321 return graph;
00322 }
00323
00327 void setGraph(GGraph* graph) {
00328 this->graph = graph;
00329 }
00330
00334 MetisGraph* getFinerGraph() {
00335 return finerGraph;
00336 }
00337
00341 void setFinerGraph(MetisGraph* finer) {
00342 finerGraph = finer;
00343 }
00344
00348 int getMinCut() {
00349 return mincut;
00350 }
00351
00355 void setMinCut(int cut) {
00356
00357 mincut = cut;
00358 }
00359
00363 void incMinCut(int cut) {
00364
00365 mincut+=cut;
00366 }
00367
00368
00369
00373 int getNumOfBoundaryNodes() {
00374 return boundaryNodes->size();
00375 }
00376
00380 void setBoundaryNode(GNode node) {
00381 node.getData(Galois::NONE).setBoundary(true);
00382
00383 boundaryNodes->insert(node);
00384
00385 }
00386
00387 void markBoundaryNode(GNode node) {
00388 node.getData(Galois::NONE).setBoundary(true);
00389 }
00390
00391
00392 void unMarkBoundaryNode(GNode node) {
00393 node.getData(Galois::NONE).setBoundary(false);
00394 }
00398 void unsetBoundaryNode(GNode node) {
00399 node.getData(Galois::NONE).setBoundary(false);
00400
00401
00402 boundaryNodes->erase(node);
00403
00404 }
00405
00409 void unsetAllBoundaryNodes() {
00410 for(GNodeSet::iterator iter = boundaryNodes->begin();iter != boundaryNodes->end();++iter){
00411 GNode node = *iter;
00412 node.getData(Galois::NONE).setBoundary(false);
00413 }
00414 boundaryNodes->clear();
00415 }
00416
00420 GNodeSet* getBoundaryNodes() {
00421 return boundaryNodes;
00422 }
00423
00424 void initBoundarySet(){
00425 if(boundaryNodes == NULL){
00426 boundaryNodes = new GNodeSet(numNodes, &gNodeToInt);
00427 }else{
00428 unsetAllBoundaryNodes();
00429 }
00430 }
00431
00435 void computeAdjWgtSums() {
00436 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00437 GNode node = *ii;
00438 node.getData(Galois::NONE).setAdjWgtSum(computeAdjWgtSum(node));
00439 }
00440 }
00441
00445 int computeCut() {
00446 int cut = 0;
00447 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00448 GNode node = *ii;
00449 for (GGraph::neighbor_iterator jj = graph->neighbor_begin(node, Galois::NONE), eejj = graph->neighbor_end(node, Galois::NONE); jj != eejj; ++jj) {
00450 GNode neighbor = *jj;
00451 if (neighbor.getData(Galois::NONE).getPartition() != node.getData(Galois::NONE).getPartition()) {
00452 int edgeWeight = (int) graph->getEdgeData(node, jj, Galois::NONE);
00453 cut = cut + edgeWeight;
00454 }
00455 }
00456 }
00457
00458 return cut/2;
00459 }
00460
00461
00465 int computeEdges() {
00466 int num = 0;
00467 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00468 GNode node = *ii;
00469 num += graph->neighborsSize(node);
00470 }
00471 return num / 2;
00472 }
00473
00477 int computeAdjWgtSum(GNode node) {
00478 int num = 0;
00479 for (GGraph::neighbor_iterator jj = graph->neighbor_begin(node, Galois::NONE), eejj = graph->neighbor_end(node, Galois::NONE); jj != eejj; ++jj) {
00480 GNode neighbor = *jj;
00481 int weight = (int) graph->getEdgeData(node, jj, Galois::NONE);
00482 num = num + weight;
00483 }
00484 return num;
00485 }
00486
00491 bool verify() {
00492 int computedCut = computeCut();
00493 if (mincut == computedCut) {
00494 cout<<"mincut is computed correctly:" << mincut <<endl;;
00495 return true;
00496 } else {
00497 cout<<"mincut is computed wrongly:" << mincut << " is not equal " << computedCut <<endl;
00498 return false;
00499 }
00500 }
00501
00505 bool isBalanced(float* tpwgts, float ubfactor) {
00506
00507 int sum = 0;
00508 for (size_t i = 0; i < partWeights.size(); i++) {
00509 sum += partWeights[i];
00510 }
00511 for (size_t i = 0; i < partWeights.size(); i++) {
00512 if (partWeights[i] > tpwgts[i] * sum * (ubfactor + 0.005)) {
00513 return false;
00514 }
00515 }
00516 return true;
00517 }
00518
00519 void computeKWayBalanceBoundary() {
00520 unsetAllBoundaryNodes();
00521 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00522 GNode node = *ii;
00523 if (node.getData().getEdegree() > 0) {
00524 setBoundaryNode(node);
00525 }
00526 }
00527
00528 }
00529
00530 void computeKWayBoundary() {
00531 unsetAllBoundaryNodes();
00532 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00533 GNode node = *ii;
00534 MetisNode& nodeData = node.getData();
00535 if (nodeData.getEdegree() - nodeData.getIdegree() >= 0) {
00536 setBoundaryNode(node);
00537 }
00538 }
00539 }
00540
00541 float computePartitionBalance(int nparts){
00542 vector<int> kpwgts(nparts);
00543
00544 for (GGraph::active_iterator ii = graph->active_begin(), ee = graph->active_end(); ii != ee; ++ii) {
00545 GNode node = *ii;
00546 kpwgts[node.getData().getPartition()]++;
00547 }
00548 float sumKpwgts=0;
00549 int maxKpwgts=0;
00550 for(int i=0;i<nparts;i++){
00551 sumKpwgts+=kpwgts[i];
00552 if(maxKpwgts < kpwgts[i])
00553 maxKpwgts = kpwgts[i];
00554 }
00555 return nparts * maxKpwgts / sumKpwgts;
00556 }
00557
00558
00559 private:
00560 vector<int> partWeights;
00561 int mincut;
00562 int numEdges;
00563 int numNodes;
00564 MetisGraph* finerGraph;
00565 GGraph* graph;
00566 GNodeSet* boundaryNodes;
00567
00568 GNode* matches;
00569 bool* matchFlag;
00570
00571 GNode* subGraphMaps;
00572
00573 GNode* coarseGraphMapTo;
00574 };
00575 #endif