Graph.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020                                                                         
00021 // $Revision: 1.7 $
00022 // $Date: 2006/05/26 18:23:16 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/graph/graph/Graph.cpp,v $
00024                                                                         
00025                                                                         
00026 // Written: fmk 
00027 // Created: 11/96
00028 // Revision: A
00029 //
00030 // Description: This file contains the class implementation for Graph.
00031 //
00032 // What: "@(#) Graph.C, revA"
00033 
00034 #include <Graph.h>
00035 #include <Vertex.h>
00036 #include <VertexIter.h>
00037 #include <MapOfTaggedObjects.h>
00038 #include <Channel.h>
00039 #include <FEM_ObjectBroker.h>
00040 #include <Vector.h>
00041 
00042 Graph::Graph()
00043   :myVertices(0), theVertexIter(0), numEdge(0), nextFreeTag(START_VERTEX_NUM)
00044 {
00045     myVertices = new MapOfTaggedObjects();
00046     theVertexIter = new VertexIter(myVertices);
00047 }
00048 
00049 
00050 Graph::Graph(int numVertices)
00051   :myVertices(0), theVertexIter(0), numEdge(0), nextFreeTag(START_VERTEX_NUM)
00052 {
00053     myVertices = new MapOfTaggedObjects();
00054     theVertexIter = new VertexIter(myVertices);
00055 }
00056 
00057 
00058 Graph::Graph(TaggedObjectStorage &theVerticesStorage)
00059   :myVertices(&theVerticesStorage), theVertexIter(0), numEdge(0), nextFreeTag(START_VERTEX_NUM)
00060 {
00061   TaggedObject *theObject;
00062   TaggedObjectIter &theObjects = theVerticesStorage.getComponents();
00063   while ((theObject = theObjects()) != 0) 
00064     if (theObject->getTag() > nextFreeTag)
00065       nextFreeTag = theObject->getTag() + 1;
00066 
00067   theVerticesStorage.clearAll();
00068   theVertexIter = new VertexIter(myVertices);
00069 }
00070     
00071 
00072 Graph::Graph(Graph &other) 
00073   :myVertices(0), theVertexIter(0), numEdge(0), nextFreeTag(START_VERTEX_NUM)
00074 {
00075   myVertices = new MapOfTaggedObjects();
00076   theVertexIter = new VertexIter(myVertices);
00077 
00078   VertexIter &otherVertices = other.getVertices();
00079   Vertex *vertexPtr;
00080 
00081   // loop through other creating vertices if tag not the same in this
00082   while ((vertexPtr = otherVertices()) != 0) {
00083     int vertexTag = vertexPtr->getTag();
00084     int vertexRef = vertexPtr->getRef();
00085     vertexPtr = new Vertex(vertexTag, vertexRef);
00086     if (vertexPtr == 0) {
00087       opserr << "Graph::Graph - out of memory\n";
00088       return;
00089     }
00090     this->addVertex(vertexPtr, false);
00091   }
00092 
00093   // loop through other adding all the edges that exist in other
00094   VertexIter &otherVertices2 = other.getVertices();
00095   while ((vertexPtr = otherVertices2()) != 0) {
00096     int vertexTag = vertexPtr->getTag();
00097     const ID &adjacency = vertexPtr->getAdjacency();
00098     for (int i=0; i<adjacency.Size(); i++) {
00099       if (this->addEdge(vertexTag, adjacency(i)) < 0) {
00100         opserr << "Graph::merge - could not add an edge!\n";
00101         return;
00102       }
00103     }
00104   }
00105 }
00106 
00107 Graph::~Graph()
00108 {
00109     // invoke delete on the Vertices
00110     myVertices->clearAll();
00111     
00112     if (myVertices != 0)
00113         delete myVertices;
00114     
00115     if (theVertexIter != 0)
00116         delete theVertexIter;
00117 }
00118 
00119 
00120 // bool addVertex(int vertexTag, int vertexRef, 
00121 //               int vertexWeight=0, int vertexColor = 0) 
00122 // Method to add a vertex to the graph. If the adjacency list
00123 // of the vertex is not empty the graph will first check to see all
00124 // vertices in the the the vertices adjacency list exist in the graph
00125 // before the vertex is added. 
00126 
00127 bool
00128 Graph::addVertex(Vertex *vertexPtr, bool checkAdjacency)
00129 {
00130     // check the vertex * and its adjacency list
00131     if (vertexPtr == 0) {
00132         opserr << "WARNING Graph::addVertex";
00133         opserr << " - attempting to add a NULL vertex*\n";
00134         return false;
00135     }
00136 
00137     if (checkAdjacency == true) {
00138         if (vertexPtr->getDegree() != 0) {
00139             const ID &adjacency = vertexPtr->getAdjacency();
00140             int size = adjacency.Size();
00141             for (int i=0; i<size; i++) {
00142                 Vertex *other = this->getVertexPtr(adjacency(i));
00143                 if (other == 0) {
00144                     opserr << "WARNING Graph::addVertex";
00145                     opserr << " - vertex with adjacent vertex not in graph\n";
00146                     return false;
00147                 }               
00148             }
00149         }
00150     }
00151 
00152 
00153     bool result = myVertices->addComponent(vertexPtr);
00154     if (result == false) {
00155       opserr << *this;
00156       opserr << "BAD VERTEX\n: " << *vertexPtr;
00157         opserr << "WARNING Graph::addVertex";
00158         opserr << " - vertex could not be stored in TaggedObjectStorage object\n";
00159     }
00160 
00161 
00162     // check nextFreeTag
00163     if (vertexPtr->getTag() >= nextFreeTag)
00164       nextFreeTag = vertexPtr->getTag() + 1;
00165 
00166     return result;
00167 }
00168 
00169 
00170 // int addEdge(int vertexTag, int otherVertexTag);
00171 // Causes the Graph to add an edge {\em (vertexTag,otherVertexTag)} to
00172 // the Graph. A check is first made to see if vertices with tags given by
00173 // {\em vertexTag} and {\em otherVertexTag} exist in the graph. If they
00174 // do not exist a $-1$ is returned, otherwise the method invokes {\em
00175 // addEdge()} on each of the corresponding vertices in the 
00176 // graph. Returns $0$ if sucessfull, a negative number if not.
00177 
00178 int 
00179 Graph::addEdge(int vertexTag, int otherVertexTag)
00180 {
00181     // get pointers to the vertices, if one does not exist return
00182 
00183     Vertex *vertex1 = this->getVertexPtr(vertexTag);
00184     Vertex *vertex2 = this->getVertexPtr(otherVertexTag);
00185     if ((vertex1 == 0) || (vertex2 == 0)) {
00186         opserr << "WARNING Graph::addEdge() - one or both of the vertices ";
00187         opserr << vertexTag << " " << otherVertexTag << " not in Graph\n";
00188         return -1;
00189     }
00190 
00191     // add an edge to each vertex
00192     int result = vertex1->addEdge(otherVertexTag);
00193         if (result == 1)
00194                 return 0;  // already there
00195         else if (result == 0) {  // added to vertexTag now add to other
00196                 if ((result = vertex2->addEdge(vertexTag)) == 0) {
00197                         numEdge++;
00198                 }
00199                 else {
00200                         opserr << " WARNING Graph::addEdge() - " << vertexTag;
00201                         opserr << " added to " << otherVertexTag;
00202                         opserr << " adjacency - but already there in otherVertexTag!.\n";
00203                         opserr << *this; exit(0);
00204                         return -2;
00205                 }
00206         } else {
00207                         opserr << " WARNING Graph::addEdge() - " << vertexTag;
00208                         opserr << " added to " << otherVertexTag;
00209                         opserr << " adjacency - but not vica versa!.\n";
00210                         opserr << *this; exit(0);
00211                         return -2;
00212         }
00213     return result;
00214 }
00215 
00216 
00217 Vertex *
00218 Graph::getVertexPtr(int vertexTag)
00219 {
00220     TaggedObject *res = myVertices->getComponentPtr(vertexTag);
00221     if (res == 0) return 0;
00222     Vertex *result = (Vertex *)res;
00223     return result;
00224 }
00225 
00226 
00227 VertexIter &
00228 Graph::getVertices(void) 
00229 {
00230     // reset the iter and then return it
00231     theVertexIter->reset();
00232     return *theVertexIter;
00233 }
00234 
00235 
00236 int 
00237 Graph::getNumVertex(void) const
00238 {
00239     return myVertices->getNumComponents();
00240 }
00241 
00242 int 
00243 Graph::getNumEdge(void) const
00244 {
00245     return numEdge;
00246 }
00247 
00248 int 
00249 Graph::getFreeTag(void) 
00250 {
00251   return nextFreeTag;
00252 }
00253 
00254 Vertex *
00255 Graph::removeVertex(int tag, bool flag)
00256 {
00257     TaggedObject *mc = myVertices->removeComponent(tag);
00258     if (mc == 0) return 0;
00259     Vertex *result = (Vertex *)mc;
00260     
00261     if (flag == true) { // remove all edges associated with the vertex
00262         opserr << "Graph::removeVertex(int tag, bool flag = true)";
00263         opserr << " - no code to remove edges yet\n";
00264         return 0;
00265     }
00266     return result;
00267 }
00268 
00269 
00270 int
00271 Graph::merge(Graph &other) {
00272 
00273   int result =0;
00274   VertexIter &otherVertices = other.getVertices();
00275   Vertex *vertexPtrOther;
00276 
00277   // loop through other creating vertices if tag not the same in this
00278   while ((vertexPtrOther = otherVertices()) != 0) {
00279     int vertexTag = vertexPtrOther->getTag();
00280     Vertex *vertexPtr = this->getVertexPtr(vertexTag);
00281     if (vertexPtr == 0) {
00282       int vertexRef = vertexPtrOther->getRef();
00283       vertexPtr = new Vertex(vertexTag, vertexRef);
00284       if (vertexPtr == 0) {
00285         opserr << "Graph::merge - out of memory\n";
00286         return -1;
00287       }
00288       this->addVertex(vertexPtr, false);
00289     }
00290   }
00291 
00292 
00293   // loop through other adding all the edges that exist in other
00294   VertexIter &otherVertices2 = other.getVertices();
00295   while ((vertexPtrOther = otherVertices2()) != 0) {
00296     int vertexTag = vertexPtrOther->getTag();
00297     const ID &adjacency = vertexPtrOther->getAdjacency();
00298     for (int i=0; i<adjacency.Size(); i++) {
00299       if (this->addEdge(vertexTag, adjacency(i)) < 0) {
00300         opserr << "Graph::merge - could not add an edge!\n";
00301         return -2;      
00302       }
00303     }
00304   }
00305   
00306   return result;
00307 }
00308 
00309 
00310 void 
00311 Graph::Print(OPS_Stream &s, int flag)
00312 {
00313     myVertices->Print(s, flag);
00314 }
00315 
00316 
00317 OPS_Stream &operator<<(OPS_Stream &s, Graph &M)
00318 {
00319   M.Print(s);
00320   return s;
00321 }
00322 
00323 
00324 int 
00325 Graph::sendSelf(int commitTag, Channel &theChannel)
00326 {
00327   // check not a datastore .. 
00328   if (theChannel.isDatastore() != 0) {
00329     opserr << "Graph::sendSelf() - does not at present send to a database\n";
00330     return -1;
00331   }
00332 
00333   int numVertex = this->getNumVertex();
00334 
00335   // send numEdge & the number of vertices
00336   static ID idData(2);
00337   idData(0) = numEdge;
00338   idData(1) = numVertex;
00339   if (theChannel.sendID(0, commitTag, idData) < 0) {
00340     opserr << "Graph::sendSelf() - failed to send the id\n";
00341     return -3;
00342   }
00343 
00344   if (numVertex != 0) {
00345     int *vertexData = new int[5 * numVertex + 2 * numEdge];
00346     Vector vertexWeights(numVertex);
00347     if (vertexData != 0) {
00348       VertexIter &theVertices = this->getVertices();
00349       Vertex *vertexPtr;
00350       int adjacencyLocation = 5 * numVertex;
00351       int vertexLocation = 0;
00352       int weightLoc = 0;
00353       while ((vertexPtr = theVertices()) != 0) {
00354         int tag = vertexPtr->getTag();
00355         int color = vertexPtr->getColor();
00356         int ref = vertexPtr->getRef();
00357         int tmp = vertexPtr->getTmp();
00358         const ID &adjacency = vertexPtr->getAdjacency();
00359         int adjSize = adjacency.Size();
00360         vertexData[vertexLocation++] = tag;
00361         vertexData[vertexLocation++] = ref;
00362         vertexData[vertexLocation++] = color;
00363         vertexData[vertexLocation++] = tmp;
00364         vertexData[vertexLocation++] = adjSize;
00365         for (int i=0; i<adjSize; i++)
00366           vertexData[adjacencyLocation++] = adjacency(i);         
00367         vertexWeights[weightLoc++] = vertexPtr->getWeight();
00368 
00369       }  
00370 
00371       ID verticesData(vertexData, adjacencyLocation, true);
00372       if (theChannel.sendID(0, commitTag, verticesData) < 0) {
00373         opserr << "Graph::sendSelf() - failed to send the id\n";
00374         return -3;
00375       }
00376       if (theChannel.sendVector(0, commitTag, vertexWeights) < 0) {
00377         opserr << "Graph::sendSelf() - failed to send the id\n";
00378         return -3;
00379       }
00380     }
00381   }
00382   /* ************ OLD --- SENDING IND VERTICES *********************
00383   VertexIter &theVertices = this->getVertices();
00384   Vertex *vertexPtr;
00385   while ((vertexPtr = theVertices()) != 0) {
00386     if (vertexPtr->sendSelf(commitTag, theChannel) < 0) {
00387       opserr << "Graph::sendSelf() - failed to send a vertex: " << *vertexPtr;
00388       return -3;
00389     }
00390   }
00391   ********************************************************************/
00392 
00393   return 0;
00394 }
00395 
00396 
00397 int 
00398 Graph::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker) 
00399 {
00400   // check not from a datastore
00401   if (theChannel.isDatastore() != 0) {
00402     opserr << "Graph::recvSelf() - at present does not receive from a database\n";
00403     return -1;
00404   }
00405 
00406   // check blank
00407   if (this->getNumVertex() != 0) {
00408     opserr << "Graph::recvSelf() - can only receive to an empty graph at present\n";
00409 
00410     numEdge = 0;
00411     myVertices->clearAll();
00412   }
00413 
00414   // recv numEdge & numVertices
00415   static ID idData(2);
00416   if (theChannel.recvID(0, commitTag, idData) < 0) {
00417     opserr << "Graph::recvSelf() - failed to receive the id\n";
00418     return -3;
00419   }
00420 
00421   numEdge = idData(0);
00422   int numVertex = idData(1);
00423 
00424   if (numVertex != 0) {
00425     
00426     int *vertexData = new int[5 * numVertex + 2 * numEdge];
00427     if (vertexData != 0) {
00428       ID verticesData(vertexData, 5*numVertex + 2 * numEdge, true);
00429       if (theChannel.recvID(0, commitTag, verticesData) < 0) {
00430         opserr << "Graph::sendSelf() - failed to send the id\n";
00431         return -3;
00432       }
00433       Vector vertexWeights(numVertex);
00434       if (theChannel.recvVector(0, commitTag, vertexWeights) < 0) {
00435         opserr << "Graph::sendSelf() - failed to send the id\n";
00436         return -3;
00437       }
00438       
00439       int adjacencyLocation = 5 * numVertex;
00440       int vertexLocation = 0;
00441       for (int i=0; i<numVertex; i++) {
00442         int tag = vertexData[vertexLocation++];
00443         int ref = vertexData[vertexLocation++];
00444         int color = vertexData[vertexLocation++];
00445         int tmp = vertexData[vertexLocation++];
00446         int adjSize = vertexData[vertexLocation++];
00447         Vertex *theVertex = new Vertex(tag, ref);
00448         if (theVertex == 0) {
00449           opserr << "Graph::recvSelf() - out of memory\n";
00450           return -4;
00451         }
00452         theVertex->setColor(color);
00453         theVertex->setTmp(tmp);
00454         theVertex->setWeight(vertexWeights(i));
00455         for (int i=0; i<adjSize; i++) {
00456           int edge = vertexData[adjacencyLocation++];
00457           theVertex->addEdge(edge);
00458         }
00459         this->addVertex(theVertex, false);
00460       }
00461     } else {
00462       opserr << "Graph::recvSelf() - out of memory\n";
00463       return -5;
00464     }
00465   }
00466   /* ************ OLD --- RECEIVING IND VERTICES *********************
00467 
00468   // for each vertex to be received, create it, receive it and then add it to the graph
00469   for (int i=0; i<numVertex; i++) {
00470     Vertex *theVertex = new Vertex(0, 0);
00471     if (theVertex == 0) {
00472       opserr << "Graph::recvSelf() - out of memory\n";
00473       return -4;
00474     }
00475     if (theVertex->recvSelf(commitTag, theChannel, theBroker) < 0) {
00476       opserr << "Graph::recvSelf() - vertex failed to receive itself\n";      
00477       return -5;
00478     }
00479     this->addVertex(theVertex, false);
00480   }
00481   ****************************************************************** */
00482   return 0;
00483 
00484 }

Generated on Mon Oct 23 15:05:12 2006 for OpenSees by doxygen 1.5.0