def bfsTree(self, root): """ calculates a breadth-first search tree from the edges in the passed HyGraph, starting from the root vertex. "Breadth-first" in the sense that all vertices reachable in step i are added to the tree before any of the newly-reachable vertices' reachable vertices are explored. The returned tree (implied in the parent relationships) consists of simple edges, not the original hyperedges of the HyGraph instance. Input Arguments: root: an integer denoting the root vertex for the tree Input Arguments: parents: a ParVec instance of length equal to the number of vertices in the HyGraph, with each element denoting the vertex number of that vertex's parent in the tree. The root is its own parent. Unreachable vertices have a parent of -1. SEE ALSO: isBfsTree """ parents = pcb.pyDenseParVec(self.nvert(), -1) fringeV = pcb.pySpParVec(self.nvert()) parents[root] = root fringeV[root] = root while fringeV.getnee() > 0: fringeV.setNumToInd() fringeE = self._spm.SpMV_SelMax(fringeV) fringeV = self._spmT.SpMV_SelMax(fringeE) pcb.EWiseMult_inplacefirst(fringeV, parents, True, -1) parents[fringeV] = 0 parents += fringeV return ParVec.toParVec(parents)
def degree(self): """ calculates the degree of each vertex of the passed HyGraph instance. Input Arguments: self: a HyGraph instance Output Argument: ret: a ParVec instance with each element containing the degree of the corresponding vertex. SEE ALSO: sum """ if self.nedge() == 0: return ParVec.zeros(self.nvert()) ret = self._spm.Reduce(pcb.pySpParMat.Column(),pcb.plus(), pcb.ifthenelse(pcb.bind2nd(pcb.not_equal_to(), 0), pcb.set(1), pcb.set(0))) return ParVec.toParVec(ret)
def npin(self): """ calculates the cardinality of each edge of the passed HyGraph instance. Input Arguments: self: a HyGraph instance Output Argument: ret: a ParVec instance with each element containing the cardinality of the corresponding edge. SEE ALSO: rank, antirank """ if self.nedge() == 0: return ParVec.zeros(self.nedge()) ret = self._spm.Reduce(pcb.pySpParMat.Row(),pcb.plus(), pcb.ifthenelse(pcb.bind2nd(pcb.not_equal_to(), 0), pcb.set(1), pcb.set(0))) return ParVec.toParVec(ret)
def __init__(self,*args): """ creates a new HyGraph instance. Can be called in one of the following forms: HyGraph(): creates a HyGraph instance with no vertices or edges. Useful as input for genGraph500Edges. HyGraph(edgeNumV, incidentVertexV, weightV, nvert, [nedge]) create a HyGraph instance. Each element of the first (ParVec) argument denotes an edge number; each corresponding element of the second (ParVec) argument denotes the number of a vertex to which the edge is incident. A single edge number can occur an arbitrary number of times in the first argument; all the vertices denoted for the same edge collectively define the hyperedge. The third argument may be a ParVec instance or a scalar; if a ParVec, then its corresponding elements denote the weight of the edge for its incident vertex; if a scalar, then it denotes the weight of all edges for all incident vertices. The nvert argument denotes the number of vertices in the resulting HyGraph (not all vertices must have incident edges). The optional nedge argument denotes the number of edges in the resulting HyGraph (not all edges must be incident vertices). Input Arguments: edgeNumV: a ParVec containing integers denoting the edge number of each edge. incidentVertexV: a ParVec containing integers denoting incident vertices. weightV: a ParVec containing double-precision floating- point numbers denoting the weight of each edge incident to a vertex, or a double-precision floating-point scalar denoting the weight of all edges for all incident vertices. nvert: an integer scalar denoting the number of vertices. nedge: an optional integer scalar argument denoting the number of edges Output Argument: ret: a HyGraph instance SEE ALSO: toParVec """ if len(args) == 0: self._spm = pcb.pySpParMat() self._spmT = pcb.pySpParMat() elif len(args) == 4: [i,j,v,nv] = args if len(i) != len(j): raise KeyError, 'first two arguments must be same length' if type(v) == int or type(v) == long or type(v) == float: v = ParVec.broadcast(len(i),v) ne = int(i.max()) + 1 if j.max() > nv-1: raise KeyError, 'at least one second index greater than #vertices' self._spm = pcb.pySpParMat(ne,nv,i._dpv,j._dpv,v._dpv) self._spmT = self._spm.copy() self._spmT.Transpose() elif len(args) == 5: [i,j,v,nv,ne] = args if len(i) != len(j): raise KeyError, 'first two arguments must be same length' if type(v) == int or type(v) == long or type(v) == float: v = ParVec.broadcast(len(i),v) if i.max() > ne-1: raise KeyError, 'at least one first index greater than #edges' if j.max() > nv-1: raise KeyError, 'at least one second index greater than #vertices' self._spm = pcb.pySpParMat(ne,nv,i._dpv,j._dpv,v._dpv) self._spmT = self._spm.copy() self._spmT.Transpose() else: raise NotImplementedError, "only 0-, 4- and 5-argument cases supported"