├── LICENSE ├── README.md ├── apps ├── BC.C ├── BFS-Bitvector.C ├── BFS.C ├── BFSCC.C ├── BellmanFord.C ├── CF.C ├── Components-Shortcut.C ├── Components.C ├── KCore.C ├── MIS.C ├── Makefile ├── PageRank.C ├── PageRankDelta.C ├── Radii.C ├── Triangle.C ├── bucketing │ ├── DeltaStepping.C │ ├── KCore.C │ ├── KCoreSerial.C │ ├── Makefile │ └── SetCover.C ├── eccentricity │ ├── CCBFS.h │ ├── CLRSTV.C │ ├── FM-Ecc.C │ ├── LogLog-Ecc.C │ ├── Makefile │ ├── RV.C │ ├── Simple-Approx-Ecc.C │ ├── TK.C │ ├── kBFS-1Phase-Ecc.C │ ├── kBFS-Ecc.C │ └── kBFS-Exact.C ├── hyper │ ├── HyperBC.C │ ├── HyperBFS.C │ ├── HyperBPath.C │ ├── HyperCC.C │ ├── HyperKCore-Efficient.C │ ├── HyperKCore.C │ ├── HyperMIS.C │ ├── HyperPageRank.C │ ├── HyperReader.C │ ├── HyperSSSP.C │ ├── Makefile │ ├── PrintBipartiteGraph.C │ └── WeightedHyperReader.C └── localAlg │ ├── ACL-Serial-Naive.C │ ├── ACL-Serial-Opt-Naive.C │ ├── ACL-Serial-Opt.C │ ├── ACL-Serial.C │ ├── ACL-Sync-Local-Opt.C │ ├── ACL-Sync-Local.C │ ├── HeatKernel-Parallel.C │ ├── HeatKernel-Randomized-Parallel.C │ ├── HeatKernel-Randomized-Serial.C │ ├── HeatKernel-Serial.C │ ├── Makefile │ ├── Nibble-Parallel.C │ ├── Nibble-Serial.C │ ├── sampleSort.h │ ├── sparseSet.h │ └── sweep.h ├── inputs ├── rMatGraph_J_5_100 └── rMatGraph_WJ_5_100 ├── ligra ├── IO.h ├── binary_search.h ├── blockRadixSort.h ├── bucket.h ├── byte-pd.h ├── byte.h ├── byteRLE-pd.h ├── byteRLE.h ├── compressedVertex.h ├── counting_sort.h ├── decoder.C ├── dyn_arr.h ├── edgeMapReduce.h ├── edgeMap_utils.h ├── encoder.C ├── gettime.h ├── graph.h ├── histogram.h ├── hygra.h ├── hypergraphDecoder.C ├── hypergraphEncoder.C ├── hypergraphIO.h ├── index_map.h ├── ligra.h ├── maybe.h ├── nibble-pd.h ├── nibble.h ├── parallel.h ├── parseCommandLine.h ├── quickSort.h ├── sequence.h ├── sequentialHT.h ├── transpose.h ├── utils.h ├── vertex.h └── vertexSubset.h ├── tutorial ├── BFS.C ├── BellmanFord.C ├── Components.C ├── KCore.C ├── Makefile ├── Radii.C └── tutorial.pdf └── utils ├── KONECTtoClique.C ├── KONECTtoHyperAdj.C ├── KONECTtoMESH.C ├── Makefile ├── SNAPtoAdj.C ├── adjGraphAddWeights.C ├── adjHypergraphAddWeights.C ├── adjToBinary.C ├── blockRadixSort.h ├── communityToClique.C ├── communityToHyperAdj.C ├── communityToMESH.C ├── graphIO.h ├── gridGraph.C ├── hyperAdjToBinary.C ├── rMatGraph.C ├── randHypergraph.C ├── randLocalGraph.C ├── transpose.h └── wghSNAPtoAdj.C /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 jshun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /apps/BFS-Bitvector.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | //Version of BFS that uses a bitvector to mark visited vertices. Works 26 | //better than BFS.C when bitvector fits in cache but Parents array 27 | //does not. 28 | #include "ligra.h" 29 | 30 | //atomically do bitwise-OR of *a with b and store in location a 31 | template 32 | inline void writeOr(ET *a, ET b) { 33 | volatile ET newV, oldV; 34 | do {oldV = *a; newV = oldV | b;} 35 | while ((oldV != newV) && !CAS(a, oldV, newV)); 36 | } 37 | 38 | struct BFS_F { 39 | uintE* Parents; long* Visited; 40 | BFS_F(uintE* _Parents, long* _Visited) 41 | : Parents(_Parents), Visited(_Visited) {} 42 | inline bool update (uintE s, uintE d) { //Update 43 | writeOr(&Visited[d/64], Visited[d/64] | ((long)1 << (d % 64))); 44 | Parents[d] = s; return 1; 45 | } 46 | inline bool updateAtomic (uintE s, uintE d){ //atomic version of Update 47 | writeOr(&Visited[d/64], Visited[d/64] | ((long)1 << (d % 64))); 48 | return (Parents[d] == UINT_E_MAX && CAS(&Parents[d],UINT_E_MAX,s)); 49 | } 50 | //cond function checks if vertex has been visited yet 51 | inline bool cond (uintE d) { 52 | return (!(Visited[d/64] & ((long)1 << (d % 64)))); } 53 | }; 54 | 55 | template 56 | void Compute(graph& GA, commandLine P) { 57 | long start = P.getOptionLongValue("-r",0); 58 | long n = GA.n; 59 | //creates Parents array, initialized to all -1, except for start 60 | uintE* Parents = newA(uintE,n); 61 | parallel_for(long i=0;i 41 | void Compute(graph& GA, commandLine P) { 42 | long start = P.getOptionLongValue("-r",0); 43 | long n = GA.n; 44 | //creates Parents array, initialized to all -1, except for start 45 | uintE* Parents = newA(uintE,n); 46 | parallel_for(long i=0;i 47 | void Compute(graph& GA, commandLine P) { 48 | long n = GA.n; 49 | //creates Parents array, initialized to all -1, except for start 50 | uintE* Parents = newA(uintE,GA.n); 51 | parallel_for(long i=0;i newDist) { 35 | ShortestPathLen[d] = newDist; 36 | if(Visited[d] == 0) { Visited[d] = 1 ; return 1;} 37 | } 38 | return 0; 39 | } 40 | inline bool updateAtomic (uintE s, uintE d, intE edgeLen){ //atomic Update 41 | intE newDist = ShortestPathLen[s] + edgeLen; 42 | return (writeMin(&ShortestPathLen[d],newDist) && 43 | CAS(&Visited[d],0,1)); 44 | } 45 | inline bool cond (uintE d) { return cond_true(d); } 46 | }; 47 | 48 | //reset visited vertices 49 | struct BF_Vertex_F { 50 | int* Visited; 51 | BF_Vertex_F(int* _Visited) : Visited(_Visited) {} 52 | inline bool operator() (uintE i){ 53 | Visited[i] = 0; 54 | return 1; 55 | } 56 | }; 57 | 58 | template 59 | void Compute(graph& GA, commandLine P) { 60 | long start = P.getOptionLongValue("-r",0); 61 | long n = GA.n; 62 | //initialize ShortestPathLen to "infinity" 63 | intE* ShortestPathLen = newA(intE,n); 64 | {parallel_for(long i=0;i 62 | void Compute(graph& GA, commandLine P) { 63 | long n = GA.n, m = GA.m; 64 | uintE* IDs = newA(uintE,n), *prevIDs = newA(uintE,n); 65 | {parallel_for(long i=0;i 53 | void Compute(graph& GA, commandLine P) { 54 | long n = GA.n; 55 | uintE* IDs = newA(uintE,n), *prevIDs = newA(uintE,n); 56 | {parallel_for(long i=0;i 0; } 41 | }; 42 | 43 | template 44 | struct Deg_LessThan_K { 45 | vertex* V; 46 | uintE* coreNumbers; 47 | intE* Degrees; 48 | uintE k; 49 | Deg_LessThan_K(vertex* _V, intE* _Degrees, uintE* _coreNumbers, uintE _k) : 50 | V(_V), k(_k), Degrees(_Degrees), coreNumbers(_coreNumbers) {} 51 | inline bool operator () (uintE i) { 52 | if(Degrees[i] < k) { coreNumbers[i] = k-1; Degrees[i] = 0; return true; } 53 | else return false; 54 | } 55 | }; 56 | 57 | template 58 | struct Deg_AtLeast_K { 59 | vertex* V; 60 | intE *Degrees; 61 | uintE k; 62 | Deg_AtLeast_K(vertex* _V, intE* _Degrees, uintE _k) : 63 | V(_V), k(_k), Degrees(_Degrees) {} 64 | inline bool operator () (uintE i) { 65 | return Degrees[i] >= k; 66 | } 67 | }; 68 | 69 | //assumes symmetric graph 70 | // 1) iterate over all remaining active vertices 71 | // 2) for each active vertex, remove if induced degree < k. Any vertex removed has 72 | // core-number (k-1) (part of (k-1)-core, but not k-core) 73 | // 3) stop once no vertices are removed. Vertices remaining are in the k-core. 74 | template 75 | void Compute(graph& GA, commandLine P) { 76 | const long n = GA.n; 77 | bool* active = newA(bool,n); 78 | {parallel_for(long i=0;i(GA.V,Degrees,coreNumbers,k)); 91 | vertexSubset remaining = vertexFilter(Frontier,Deg_AtLeast_K(GA.V,Degrees,k)); 92 | Frontier.del(); 93 | Frontier = remaining; 94 | if (0 == toRemove.numNonzeros()) { // fixed point. found k-core 95 | toRemove.del(); 96 | break; 97 | } 98 | else { 99 | edgeMap(GA,toRemove,Update_Deg(Degrees), -1, no_output); 100 | toRemove.del(); 101 | } 102 | } 103 | if(Frontier.numNonzeros() == 0) { largestCore = k-1; break; } 104 | } 105 | cout << "largestCore was " << largestCore << endl; 106 | Frontier.del(); free(coreNumbers); free(Degrees); 107 | } 108 | -------------------------------------------------------------------------------- /apps/Makefile: -------------------------------------------------------------------------------- 1 | ifdef LONG 2 | INTT = -DLONG 3 | endif 4 | 5 | ifdef EDGELONG 6 | INTE = -DEDGELONG 7 | endif 8 | 9 | ifdef PD 10 | PD = -DPD 11 | endif 12 | 13 | ifdef BYTE 14 | CODE = -DBYTE 15 | else ifdef NIBBLE 16 | CODE = -DNIBBLE 17 | else 18 | CODE = -DBYTERLE 19 | endif 20 | 21 | ifdef LOWMEM 22 | MEM = -DLOWMEM 23 | endif 24 | 25 | #compilers 26 | ifdef CILK 27 | PCC = g++ 28 | PCFLAGS = -std=c++14 -fcilkplus -lcilkrts -O3 -DCILK $(INTT) $(INTE) $(CODE) $(PD) $(MEM) 29 | PLFLAGS = -fcilkplus -lcilkrts 30 | 31 | else ifdef MKLROOT 32 | PCC = icpc 33 | PCFLAGS = -std=c++14 -O3 -DCILKP $(INTT) $(INTE) $(CODE) $(PD) $(MEM) 34 | 35 | else ifdef OPENMP 36 | PCC = g++ 37 | PCFLAGS = -std=c++14 -fopenmp -march=native -O3 -DOPENMP $(INTT) $(INTE) $(CODE) $(PD) $(MEM) 38 | 39 | else 40 | PCC = g++ 41 | PCFLAGS = -std=c++14 -O3 $(INTT) $(INTE) $(CODE) $(PD) $(MEM) 42 | endif 43 | 44 | COMMON= ligra.h graph.h compressedVertex.h vertex.h utils.h IO.h parallel.h gettime.h index_map.h maybe.h sequence.h edgeMap_utils.h binary_search.h quickSort.h blockRadixSort.h transpose.h parseCommandLine.h byte.h byteRLE.h nibble.h byte-pd.h byteRLE-pd.h nibble-pd.h vertexSubset.h encoder.C decoder.C 45 | 46 | ALL= encoder decoder BFS BC BellmanFord Components Components-Shortcut Radii PageRank PageRankDelta BFSCC BFS-Bitvector KCore MIS Triangle CF 47 | 48 | all: $(ALL) 49 | 50 | % : %.C $(COMMON) 51 | $(PCC) $(PCFLAGS) -o $@ $< 52 | 53 | $(COMMON): 54 | ln -s ../ligra/$@ . 55 | 56 | .PHONY : clean 57 | 58 | clean : 59 | rm -f *.o $(ALL) 60 | 61 | cleansrc : 62 | rm -f *.o $(ALL) 63 | rm $(COMMON) 64 | -------------------------------------------------------------------------------- /apps/PageRank.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | #include "ligra.h" 25 | #include "math.h" 26 | 27 | template 28 | struct PR_F { 29 | double* p_curr, *p_next; 30 | vertex* V; 31 | PR_F(double* _p_curr, double* _p_next, vertex* _V) : 32 | p_curr(_p_curr), p_next(_p_next), V(_V) {} 33 | inline bool update(uintE s, uintE d){ //update function applies PageRank equation 34 | p_next[d] += p_curr[s]/V[s].getOutDegree(); 35 | return 1; 36 | } 37 | inline bool updateAtomic (uintE s, uintE d) { //atomic Update 38 | writeAdd(&p_next[d],p_curr[s]/V[s].getOutDegree()); 39 | return 1; 40 | } 41 | inline bool cond (intT d) { return cond_true(d); }}; 42 | 43 | //vertex map function to update its p value according to PageRank equation 44 | struct PR_Vertex_F { 45 | double damping; 46 | double addedConstant; 47 | double* p_curr; 48 | double* p_next; 49 | PR_Vertex_F(double* _p_curr, double* _p_next, double _damping, intE n) : 50 | p_curr(_p_curr), p_next(_p_next), 51 | damping(_damping), addedConstant((1-_damping)*(1/(double)n)){} 52 | inline bool operator () (uintE i) { 53 | p_next[i] = damping*p_next[i] + addedConstant; 54 | return 1; 55 | } 56 | }; 57 | 58 | //resets p 59 | struct PR_Vertex_Reset { 60 | double* p_curr; 61 | PR_Vertex_Reset(double* _p_curr) : 62 | p_curr(_p_curr) {} 63 | inline bool operator () (uintE i) { 64 | p_curr[i] = 0.0; 65 | return 1; 66 | } 67 | }; 68 | 69 | template 70 | void Compute(graph& GA, commandLine P) { 71 | long maxIters = P.getOptionLongValue("-maxiters",100); 72 | const intE n = GA.n; 73 | const double damping = 0.85, epsilon = 0.0000001; 74 | 75 | double one_over_n = 1/(double)n; 76 | double* p_curr = newA(double,n); 77 | {parallel_for(long i=0;i(p_curr,p_next,GA.V),0, no_output); 88 | vertexMap(Frontier,PR_Vertex_F(p_curr,p_next,damping,n)); 89 | //compute L1-norm between p_curr and p_next 90 | {parallel_for(long i=0;i 28 | inline void writeOr(ET *a, ET b) { 29 | volatile ET newV, oldV; 30 | do {oldV = *a; newV = oldV | b;} 31 | while ((oldV != newV) && !CAS(a, oldV, newV)); 32 | } 33 | 34 | struct Radii_F { 35 | intE round; 36 | intE* radii; 37 | long* Visited, *NextVisited; 38 | Radii_F(long* _Visited, long* _NextVisited, intE* _radii, intE _round) : 39 | Visited(_Visited), NextVisited(_NextVisited), radii(_radii), round(_round) 40 | {} 41 | inline bool update (uintE s, uintE d){ //Update function does a bitwise-or 42 | long toWrite = Visited[d] | Visited[s]; 43 | if(Visited[d] != toWrite){ 44 | NextVisited[d] |= toWrite; 45 | if(radii[d] != round) { radii[d] = round; return 1; } 46 | } 47 | return 0; 48 | } 49 | inline bool updateAtomic (uintE s, uintE d){ //atomic Update 50 | long toWrite = Visited[d] | Visited[s]; 51 | if(Visited[d] != toWrite){ 52 | writeOr(&NextVisited[d],toWrite); 53 | intE oldRadii = radii[d]; 54 | if(radii[d] != round) return CAS(&radii[d],oldRadii,round); 55 | } 56 | return 0; 57 | } 58 | inline bool cond (uintE d) { return cond_true(d); } 59 | }; 60 | 61 | //function passed to vertex map to sync NextVisited and Visited 62 | struct Radii_Vertex_F { 63 | long* Visited, *NextVisited; 64 | Radii_Vertex_F(long* _Visited, long* _NextVisited) : 65 | Visited(_Visited), NextVisited(_NextVisited) {} 66 | inline bool operator() (uintE i) { 67 | Visited[i] = NextVisited[i]; 68 | return 1; 69 | } 70 | }; 71 | 72 | template 73 | void Compute(graph& GA, commandLine P) { 74 | long n = GA.n; 75 | intE* radii = newA(intE,n); 76 | long* Visited = newA(long,n), *NextVisited = newA(long,n); 77 | {parallel_for(long i=0;i 35 | long countCommon(vertex& A, vertex& B, uintE a, uintE b) { 36 | uintT i=0,j=0,nA = A.getOutDegree(), nB = B.getOutDegree(); 37 | uintE* nghA = (uintE*) A.getOutNeighbors(), *nghB = (uintE*) B.getOutNeighbors(); 38 | long ans=0; 39 | while (i < nA && j < nB && nghA[i] < a && nghB[j] < b) { //count "directed" triangles 40 | if (nghA[i]==nghB[j]) i++, j++, ans++; 41 | else if (nghA[i] < nghB[j]) i++; 42 | else j++; 43 | } 44 | return ans; 45 | } 46 | 47 | template 48 | struct countF { //for edgeMap 49 | vertex* V; 50 | long* counts; 51 | countF(vertex* _V, long* _counts) : V(_V), counts(_counts) {} 52 | inline bool update (uintE s, uintE d) { 53 | if(s > d) //only count "directed" triangles 54 | writeAdd(&counts[s], countCommon(V[s],V[d],s,d)); 55 | return 1; 56 | } 57 | inline bool updateAtomic (uintE s, uintE d) { 58 | if (s > d) //only count "directed" triangles 59 | writeAdd(&counts[s], countCommon(V[s],V[d],s,d)); 60 | return 1; 61 | } 62 | inline bool cond (uintE d) { return cond_true(d); } //does nothing 63 | }; 64 | 65 | struct intLT { bool operator () (uintT a, uintT b) { return a < b; }; }; 66 | 67 | template 68 | struct initF { //for vertexMap to initial counts and sort neighbors for merging 69 | vertex* V; 70 | long* counts; 71 | initF(vertex* _V, long* _counts) : V(_V), counts(_counts) {} 72 | inline bool operator () (uintE i) { 73 | counts[i] = 0; 74 | quickSort(V[i].getOutNeighbors(),V[i].getOutDegree(),intLT()); 75 | return 1; 76 | } 77 | }; 78 | 79 | template 80 | void Compute(graph& GA, commandLine P) { 81 | uintT n = GA.n; 82 | long* counts = newA(long,n); 83 | bool* frontier = newA(bool,n); 84 | {parallel_for(long i=0;i(GA.V,counts)); 88 | edgeMap(GA,Frontier,countF(GA.V,counts), -1, no_output); 89 | long count = sequence::plusReduce(counts,n); 90 | cout << "triangle count = " << count << endl; 91 | Frontier.del(); free(counts); 92 | } 93 | -------------------------------------------------------------------------------- /apps/bucketing/DeltaStepping.C: -------------------------------------------------------------------------------- 1 | #define WEIGHTED 1 2 | #include 3 | #include "ligra.h" 4 | #include "index_map.h" 5 | #include "bucket.h" 6 | 7 | constexpr uintE TOP_BIT = ((uintE)INT_E_MAX) + 1; 8 | constexpr uintE VAL_MASK = INT_E_MAX; 9 | 10 | struct Visit_F { 11 | array_imap dists; 12 | Visit_F(array_imap& _dists) : dists(_dists) { } 13 | 14 | inline Maybe update(const uintE& s, const uintE& d, const intE& w) { 15 | uintE oval = dists.s[d]; 16 | uintE dist = oval | TOP_BIT, n_dist = (dists.s[s] | TOP_BIT) + w; 17 | if (n_dist < dist) { 18 | if (!(oval & TOP_BIT)) { // First visitor 19 | dists[d] = n_dist; 20 | return Maybe(oval); 21 | } 22 | dists[d] = n_dist; 23 | } 24 | return Maybe(); 25 | } 26 | 27 | inline Maybe updateAtomic(const uintE& s, const uintE& d, const intE& w) { 28 | uintE oval = dists.s[d]; 29 | uintE dist = oval | TOP_BIT; 30 | uintE n_dist = (dists.s[s] | TOP_BIT) + w; 31 | if (n_dist < dist) { 32 | if (!(oval & TOP_BIT) && CAS(&(dists[d]), oval, n_dist)) { // First visitor 33 | return Maybe(oval); 34 | } 35 | writeMin(&(dists[d]), n_dist); 36 | } 37 | return Maybe(); 38 | } 39 | 40 | inline bool cond(const uintE& d) const { return true; } 41 | }; 42 | 43 | template 44 | void DeltaStepping(graph& G, uintE src, uintE delta, size_t num_buckets=128) { 45 | auto V = G.V; size_t n = G.n, m = G.m; 46 | auto dists = array_imap(n, [&] (size_t i) { return INT_E_MAX; }); 47 | dists[src] = 0; 48 | 49 | auto get_bkt = [&] (const uintE& dist) -> const uintE { 50 | return (dist == INT_E_MAX) ? UINT_E_MAX : (dist / delta); }; 51 | auto get_ring = [&] (const size_t& v) -> const uintE { 52 | auto d = dists[v]; 53 | return (d == INT_E_MAX) ? UINT_E_MAX : (d / delta); }; 54 | auto b = make_buckets(n, get_ring, increasing, num_buckets); 55 | 56 | auto apply_f = [&] (const uintE v, uintE& oldDist) -> void { 57 | uintE newDist = dists.s[v] & VAL_MASK; 58 | dists.s[v] = newDist; // Remove the TOP_BIT in the distance. 59 | // Compute the previous bucket and new bucket for the vertex. 60 | uintE prev_bkt = get_bkt(oldDist), new_bkt = get_bkt(newDist); 61 | bucket_dest dest = b.get_bucket(prev_bkt, new_bkt); 62 | oldDist = dest; // write back 63 | }; 64 | 65 | auto bkt = b.next_bucket(); 66 | while (bkt.id != b.null_bkt) { 67 | auto active = bkt.identifiers; 68 | // The output of the edgeMap is a vertexSubsetData where the value 69 | // stored with each vertex is its original distance in this round 70 | auto res = edgeMapData(G, active, Visit_F(dists), G.m/20, sparse_no_filter | dense_forward); 71 | vertexMap(res, apply_f); 72 | if (res.dense()) { 73 | b.update_buckets(res.get_fn_repr(), n); 74 | } else { 75 | b.update_buckets(res.get_fn_repr(), res.size()); 76 | } 77 | res.del(); active.del(); 78 | bkt = b.next_bucket(); 79 | } 80 | } 81 | 82 | template 83 | void Compute(graph& GA, commandLine P) { 84 | uintE src = P.getOptionLongValue("-src",0); 85 | uintE delta = P.getOptionLongValue("-delta",1); 86 | size_t num_buckets = P.getOptionLongValue("-nb", 128); 87 | if (num_buckets != (1 << pbbs::log2_up(num_buckets))) { 88 | cout << "Please specify a number of buckets that is a power of two" << endl; 89 | exit(-1); 90 | } 91 | cout << "### Application: Delta-Stepping" << endl; 92 | cout << "### Graph: " << P.getArgument(0) << endl; 93 | cout << "### Workers: " << getWorkers() << endl; 94 | cout << "### Buckets: " << num_buckets << endl; 95 | cout << "### n: " << GA.n << endl; 96 | cout << "### m: " << GA.m << endl; 97 | cout << "### delta = " << delta << endl; 98 | DeltaStepping(GA, src, delta, num_buckets); 99 | } 100 | -------------------------------------------------------------------------------- /apps/bucketing/KCore.C: -------------------------------------------------------------------------------- 1 | #include "ligra.h" 2 | #include "index_map.h" 3 | #include "bucket.h" 4 | #include "edgeMapReduce.h" 5 | 6 | template 7 | array_imap KCore(graph& GA, size_t num_buckets=128) { 8 | const size_t n = GA.n; const size_t m = GA.m; 9 | auto D = array_imap(n, [&] (size_t i) { return GA.V[i].getOutDegree(); }); 10 | 11 | auto em = EdgeMap(GA, make_tuple(UINT_E_MAX, 0), (size_t)GA.m/5); 12 | auto b = make_buckets(n, D, increasing, num_buckets); 13 | 14 | size_t finished = 0; 15 | while (finished != n) { 16 | auto bkt = b.next_bucket(); 17 | auto active = bkt.identifiers; 18 | uintE k = bkt.id; 19 | finished += active.size(); 20 | 21 | auto apply_f = [&] (const tuple& p) -> const Maybe > { 22 | uintE v = std::get<0>(p), edgesRemoved = std::get<1>(p); 23 | uintE deg = D.s[v]; 24 | if (deg > k) { 25 | uintE new_deg = max(deg - edgesRemoved, k); 26 | D.s[v] = new_deg; 27 | uintE bkt = b.get_bucket(deg, new_deg); 28 | return wrap(v, bkt); 29 | } 30 | return Maybe >(); 31 | }; 32 | 33 | vertexSubsetData moved = em.template edgeMapCount(active, apply_f); 34 | b.update_buckets(moved.get_fn_repr(), moved.size()); 35 | moved.del(); active.del(); 36 | } 37 | return D; 38 | } 39 | 40 | template 41 | void Compute(graph& GA, commandLine P) { 42 | size_t num_buckets = P.getOptionLongValue("-nb", 128); 43 | if (num_buckets != (1 << pbbs::log2_up(num_buckets))) { 44 | cout << "Number of buckets must be a power of two." << endl; 45 | exit(-1); 46 | } 47 | cout << "### Application: k-core" << endl; 48 | cout << "### Graph: " << P.getArgument(0) << endl; 49 | cout << "### Workers: " << getWorkers() << endl; 50 | cout << "### Buckets: " << num_buckets << endl; 51 | cout << "### n: " << GA.n << endl; 52 | cout << "### m: " << GA.m << endl; 53 | 54 | auto cores = KCore(GA, num_buckets); 55 | uintE mc = 0; 56 | for (size_t i=0; i < GA.n; i++) { mc = std::max(mc, cores[i]); } 57 | cout << "### Max core: " << mc << endl; 58 | } 59 | -------------------------------------------------------------------------------- /apps/bucketing/KCoreSerial.C: -------------------------------------------------------------------------------- 1 | #include "ligra.h" 2 | 3 | // Linear-work sequential implementation of the BZ coreness alg 4 | // Modified code from https://github.com/athomo/kcore/blob/master/src/KCoreWG_BZ.java 5 | 6 | struct decompress_f { 7 | intT* deg; 8 | intT* pos; 9 | intT* vert; 10 | intT* bin; 11 | decompress_f(intT* _deg, intT* _pos, intT* _vert, intT* _bin) : deg(_deg), pos(_pos), vert(_vert), bin(_bin) {} 12 | 13 | inline bool update (const uintE& v, const uintE& u) { 14 | if (deg[u] > deg[v]) { 15 | intT du = deg[u]; intT pu = pos[u]; 16 | intT pw = bin[du]; intT w = vert[pw]; 17 | if (u != w) { 18 | pos[u] = pw; vert[pu] = w; 19 | pos[w] = pu; vert[pw] = u; 20 | } 21 | bin[du]++; 22 | deg[u]--; 23 | } 24 | return false; 25 | } 26 | 27 | inline bool updateAtomic (uintE s, uintE d) { 28 | return update(s, d); 29 | } 30 | 31 | // Condition is checked in update. 32 | inline bool cond (uintE d) { return true; } 33 | }; 34 | 35 | template 36 | array_imap KCore(graph& G, bool printCores=false) { 37 | size_t n = G.n, m = G.m; 38 | 39 | uintE md = 0; 40 | for(size_t v=0; v vert(n); 45 | array_imap pos(n); 46 | array_imap deg(n); 47 | array_imap bin(md+1); 48 | 49 | for (size_t d=0; d<=md; d++) { 50 | bin[d] = 0; 51 | } 52 | for (size_t v=0; v=1; d--) { 75 | bin[d] = bin[d-1]; 76 | } 77 | bin[0] = 0; 78 | 79 | auto df = decompress_f(deg.s, pos.s, vert.s, bin.s); 80 | 81 | // Main algorithm. 82 | auto vs = vertexSubset(n, (uintE)0); 83 | for (size_t i = 0; i < n; i++) { 84 | intT v = vert[i]; // Smallest degree vertex in the remaining graph. 85 | vs.s[0] = v; 86 | edgeMap(G, vs, df, -1, no_output | no_dense); 87 | } 88 | vs.del(); 89 | 90 | if (printCores) { 91 | for (size_t i=0; i 105 | void Compute(graph& GA, commandLine P) { 106 | bool printCores = P.getOptionValue("-p"); 107 | cout << "### application: k-core-serial" << endl; 108 | cout << "### graph: " << P.getArgument(0) << endl; 109 | cout << "### workers: " << getWorkers() << endl; 110 | cout << "### n: " << GA.n << endl; 111 | cout << "### m: " << GA.m << endl; 112 | auto cores = KCore(GA, printCores); 113 | } 114 | -------------------------------------------------------------------------------- /apps/bucketing/Makefile: -------------------------------------------------------------------------------- 1 | ifdef LONG 2 | INTT = -DLONG 3 | endif 4 | 5 | ifdef EDGELONG 6 | INTE = -DEDGELONG 7 | endif 8 | 9 | ifdef PD 10 | PD = -DPD 11 | endif 12 | 13 | ifdef BYTE 14 | CODE = -DBYTE 15 | else ifdef NIBBLE 16 | CODE = -DNIBBLE 17 | else 18 | CODE = -DBYTERLE 19 | endif 20 | 21 | #compilers 22 | ifdef CILK 23 | PCC = g++ 24 | PCFLAGS = -std=c++14 -fcilkplus -lcilkrts -O3 -DCILK $(INTT) $(INTE) $(CODE) $(PD) $(FLAGS) 25 | PLFLAGS = -fcilkplus -lcilkrts 26 | 27 | else ifdef MKLROOT 28 | PCC = icpc 29 | PCFLAGS = -std=c++14 -O3 -DCILKP $(INTT) $(INTE) $(CODE) $(PD) 30 | 31 | else ifdef OPENMP 32 | PCC = g++ 33 | PCFLAGS = -std=c++14 -fopenmp -march=native -O3 -DOPENMP $(INTT) $(INTE) $(CODE) $(PD) 34 | 35 | else 36 | PCC = g++ 37 | PCFLAGS = -std=c++14 -O3 $(INTT) $(INTE) $(CODE) $(PD) 38 | endif 39 | 40 | COMMON= ligra.h edgeMap_utils.h index_map.h sequence.h maybe.h binary_search.h graph.h compressedVertex.h vertex.h utils.h IO.h parallel.h gettime.h quickSort.h blockRadixSort.h transpose.h parseCommandLine.h byte.h byteRLE.h nibble.h byte-pd.h byteRLE-pd.h nibble-pd.h vertexSubset.h encoder.C bucket.h counting_sort.h dyn_arr.h edgeMapReduce.h histogram.h sequentialHT.h 41 | 42 | ALL= DeltaStepping KCore KCoreSerial SetCover 43 | 44 | all: $(ALL) 45 | 46 | % : %.C $(COMMON) 47 | $(PCC) $(PCFLAGS) -o $@ $< 48 | 49 | $(COMMON): 50 | ln -s ../../ligra/$@ . 51 | 52 | .PHONY : clean 53 | 54 | clean : 55 | rm -f *.o $(ALL) 56 | 57 | cleansrc : 58 | rm -f *.o $(ALL) 59 | rm $(COMMON) 60 | -------------------------------------------------------------------------------- /apps/eccentricity/CCBFS.h: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | #include "ligra.h" 25 | 26 | //BFS portion 27 | struct CCBFS_F { 28 | intE label; 29 | intE* Labels; 30 | CCBFS_F(intE _label, intE* _Labels) : label(_label), Labels(_Labels) {} 31 | inline bool update(const intE &s, const intE& d) { 32 | if(Labels[d] == INT_E_MAX) { Labels[d] = label; return 1; } 33 | else return 0; } 34 | inline bool updateAtomic(const intE &s, const intE &d) { 35 | return (CAS(&Labels[d],INT_E_MAX,label)); } 36 | //cond function checks if vertex has been visited yet 37 | inline bool cond(const uintE &d) { return Labels[d] == INT_E_MAX;}}; 38 | 39 | template 40 | uintE CCBFS(intE start, graph GA, intE* Labels) { 41 | long n = GA.n; 42 | Labels[start] = start; 43 | vertexSubset Frontier(n,start); //creates initial frontier 44 | intE label = -start-1; 45 | long round = 0, numVisited = 0; 46 | while(!Frontier.isEmpty()){ //loop until frontier is empty 47 | round++; 48 | numVisited+=Frontier.numNonzeros(); 49 | //apply edgemap 50 | vertexSubset output = edgeMap(GA, Frontier, CCBFS_F(label,Labels), GA.m/20); 51 | Frontier.del(); 52 | Frontier = output; //set new frontier 53 | } 54 | Frontier.del(); 55 | return numVisited; 56 | } 57 | 58 | //CC portion 59 | //update function writes min ID 60 | struct CC_F { 61 | intE* IDs, *prevIDs; 62 | CC_F(intE* _IDs, intE* _prevIDs) : 63 | IDs(_IDs), prevIDs(_prevIDs) {} 64 | inline bool update(const uintE &s, const uintE &d){ 65 | intE origID = IDs[d]; 66 | if(IDs[s] < origID) { IDs[d] = min(origID,IDs[s]); 67 | if(origID == prevIDs[d]) return 1; 68 | } return 0; } 69 | inline bool updateAtomic(const uintE &s, const uintE &d){ 70 | intE origID = IDs[d]; 71 | return (writeMin(&IDs[d],IDs[s]) 72 | && origID == prevIDs[d]);} 73 | //don't consider vertices visited by BFS (they have negative labels) 74 | inline bool cond(const uintE &d) { return prevIDs[d] >= 0;}}; 75 | 76 | //function used by vertex map to sync prevIDs with IDs 77 | struct CC_Vertex_F { 78 | intE* IDs, *prevIDs; 79 | CC_Vertex_F(intE* _IDs, intE* _prevIDs) : 80 | IDs(_IDs), prevIDs(_prevIDs) {} 81 | inline bool operator () (const uintE &i) { 82 | prevIDs[i] = IDs[i]; 83 | return 1; }}; 84 | 85 | template 86 | void Components(graph GA, intE* IDs) { 87 | long n = GA.n; 88 | intE* prevIDs = newA(intE,n); 89 | //initial frontier contains all unvisited vertices 90 | bool* frontier = newA(bool,n); 91 | parallel_for(long i=0;i 42 | void Compute(hypergraph& GA, commandLine P) { 43 | long start = P.getOptionLongValue("-r",0); 44 | long nv = GA.nv, nh = GA.nh; 45 | //creates Parents array, initialized to all -1, except for start 46 | uintE* ParentsV = newA(uintE,nv); 47 | uintE* ParentsH = newA(uintE,nh); 48 | {parallel_for(long i=0;i 56 | void Compute(hypergraph& GA, commandLine P) { 57 | long start = P.getOptionLongValue("-r",0); 58 | long nv = GA.nv, nh = GA.nh; 59 | //creates Parents array, initialized to all -1, except for start 60 | uintE* ParentsV = newA(uintE,nv); 61 | intE* ParentsH = newA(intE,nh); //init to negative in-degree 62 | {parallel_for(long i=0;i 54 | void Compute(hypergraph& GA, commandLine P) { 55 | long nv = GA.nv, nh = GA.nh; 56 | uintE* IDsV = newA(uintE,nv), *prevIDsV = newA(uintE,nv); 57 | uintE* IDsH = newA(uintE,nh), *prevIDsH = newA(uintE,nh); 58 | {parallel_for(long i=0;i 21 | array_imap KCore(hypergraph& GA, size_t num_buckets=128) { 22 | const size_t nv = GA.nv, mv = GA.mv, nh = GA.nh; 23 | bool* active = newA(bool,nv); 24 | {parallel_for(long i=0;i(GA.nv, [&] (size_t i) { return GA.V[i].getOutDegree(); }); 33 | 34 | auto hp = HypergraphProp(GA, make_tuple(UINT_E_MAX, 0), (size_t)GA.mv/5); 35 | auto b = make_buckets(nv, D, increasing, num_buckets); 36 | 37 | size_t finished = 0; 38 | while (finished != nv) { 39 | auto bkt = b.next_bucket(); 40 | auto active = bkt.identifiers; 41 | uintE k = bkt.id; 42 | finished += active.size(); 43 | 44 | auto apply_f = [&] (const tuple& p) -> const Maybe > { 45 | uintE v = std::get<0>(p), edgesRemoved = std::get<1>(p); 46 | uintE deg = D.s[v]; 47 | if (deg > k) { 48 | uintE new_deg = max(deg - edgesRemoved, k); 49 | D.s[v] = new_deg; 50 | uintE bkt = b.get_bucket(deg, new_deg); 51 | return wrap(v, bkt); 52 | } 53 | return Maybe >(); 54 | }; 55 | 56 | hyperedgeSubset FrontierH = vertexProp(GA,active,Remove_Hyperedge(Flags)); 57 | //cout << "k="<()) << endl; 79 | } 80 | -------------------------------------------------------------------------------- /apps/hyper/HyperPageRank.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | #define HYPER 1 25 | #include "hygra.h" 26 | #include "math.h" 27 | 28 | template 29 | struct PR_Update_F { 30 | double* pSrc, *pDest; 31 | vertex* V; 32 | PR_Update_F(double* _pSrc, double* _pDest, vertex* _V) : 33 | pSrc(_pSrc), pDest(_pDest), V(_V) {} 34 | inline bool update(uintE s, uintE d){ //update function applies PageRank equation 35 | pDest[d] += pSrc[s]/V[s].getOutDegree(); 36 | return 1; 37 | } 38 | inline bool updateAtomic (uintE s, uintE d) { //atomic Update 39 | writeAdd(&pDest[d],pSrc[s]/V[s].getOutDegree()); 40 | return 1; 41 | } 42 | inline bool cond (intT d) { return cond_true(d); }}; 43 | 44 | //vertex map function to update its p value according to PageRank equation 45 | struct PR_Vertex_F { 46 | double damping; 47 | double addedConstant; 48 | double* pV; 49 | PR_Vertex_F(double* _pV, double _damping, intE n) : 50 | pV(_pV), damping(_damping), addedConstant((1-_damping)*(1/(double)n)){} 51 | inline bool operator () (uintE i) { 52 | pV[i] = damping*pV[i] + addedConstant; 53 | return 1; 54 | } 55 | }; 56 | 57 | //resets p 58 | struct PR_Reset { 59 | double* p; 60 | PR_Reset(double* _p) : 61 | p(_p) {} 62 | inline bool operator () (uintE i) { 63 | p[i] = 0.0; 64 | return 1; 65 | } 66 | }; 67 | 68 | struct Entropy_F { 69 | double* EntropyH, *pH, *pV; 70 | Entropy_F(double* _EntropyH, double* _pH, double* _pV) : 71 | EntropyH(_EntropyH), pH(_pH), pV(_pV) {} 72 | inline bool update(uintE s, uintE d){ //update function applies PageRank equation 73 | EntropyH[d] += (pV[s]/pH[d])*log2(pH[d]/pV[s]); 74 | return 1; 75 | } 76 | inline bool updateAtomic (uintE s, uintE d) { //atomic Update 77 | writeAdd(&EntropyH[d],(pV[s]/pH[d])*log2(pH[d]/pV[s])); 78 | return 1; 79 | } 80 | inline bool cond (intT d) { return cond_true(d); }}; 81 | 82 | //assumes connected graph, otherwise PageRank mass will be lost 83 | //pass -entropy flag to compute entropy of hyperedges at the end 84 | template 85 | void Compute(hypergraph& GA, commandLine P) { 86 | long maxIters = P.getOptionLongValue("-maxiters",1); 87 | bool entropy = P.getOptionValue("-entropy"); 88 | const intE nv = GA.nv, nh = GA.nh; 89 | const double damping = 0.85, epsilon = 0.0000001; 90 | 91 | double one_over_nv = 1/(double)nv; 92 | double* pV = newA(double,nv); 93 | {parallel_for(long i=0;i(pV,pH,GA.V),0,no_output); 108 | vertexMap(FrontierV,PR_Reset(pV)); 109 | //cout << "H sum: " << sequence::plusReduce(pH,nh) << endl; 110 | hyperedgeProp(GA,FrontierH,PR_Update_F(pH,pV,GA.H),0,no_output); 111 | vertexMap(FrontierV,PR_Vertex_F(pV,damping,nv)); 112 | } 113 | if(entropy) { 114 | double* EntropyH = newA(double,nh); 115 | {parallel_for(long i=0;i 28 | void Compute(hypergraph& GA, commandLine P) { 29 | long n = GA.nv; 30 | cout << "vertices\n"; 31 | for(long i=0;i newDist) { 36 | ShortestPathLenDest[d] = newDist; 37 | if(Visited[d] == 0) { Visited[d] = 1 ; return 1;} 38 | } 39 | return 0; 40 | } 41 | inline bool updateAtomic (uintE s, uintE d, intE edgeLen){ //atomic Update 42 | intE newDist = ShortestPathLenSrc[s] + edgeLen; 43 | return (writeMin(&ShortestPathLenDest[d],newDist) && 44 | CAS(&Visited[d],0,1)); 45 | } 46 | inline bool cond (uintE d) { return cond_true(d); } 47 | }; 48 | 49 | //reset visited elements 50 | struct BF_Reset_F { 51 | int* Visited; 52 | BF_Reset_F(int* _Visited) : Visited(_Visited) {} 53 | inline bool operator() (uintE i){ 54 | Visited[i] = 0; 55 | return 1; 56 | } 57 | }; 58 | 59 | template 60 | void Compute(hypergraph& GA, commandLine P) { 61 | long start = P.getOptionLongValue("-r",0); 62 | long nv = GA.nv, nh = GA.nh; 63 | //initialize ShortestPathLen to "infinity" 64 | intE* ShortestPathLenV = newA(intE,nv); 65 | intE* ShortestPathLenH = newA(intE,nh); 66 | {parallel_for(long i=0;i 2 | #include 3 | #include 4 | #include "parallel.h" 5 | #include "gettime.h" 6 | #include "utils.h" 7 | #include "graph.h" 8 | #include "hypergraphIO.h" 9 | #include "parseCommandLine.h" 10 | #include "vertex.h" 11 | using namespace std; 12 | 13 | int parallel_main(int argc, char* argv[]) { 14 | commandLine P(argc,argv," "); 15 | char* iFile = P.getArgument(0); 16 | 17 | hypergraph G = 18 | readHypergraphFromFile(iFile,1,0); 19 | 20 | long n = G.nv; 21 | cout << "left side\n"; 22 | for(long i=0;i 29 | void Compute(hypergraph& GA, commandLine P) { 30 | long n = GA.nv; 31 | cout << "vertices\n"; 32 | for(long i=0;i 31 | #include 32 | #include "sweep.h" 33 | using namespace std; 34 | 35 | typedef pair pairDouble; 36 | typedef pair pairIF; 37 | struct pq_compare { bool operator () (pairIF a, pairIF b) { 38 | return a.second > b.second; }}; 39 | 40 | timer t1; 41 | template 42 | void Compute(graph& GA, commandLine P) { 43 | t1.start(); 44 | long start = P.getOptionLongValue("-r",0); 45 | if(GA.V[start].getOutDegree() == 0) { 46 | cout << "starting vertex has degree 0" << endl; 47 | return; 48 | } 49 | const double alpha = P.getOptionDoubleValue("-a",0.15); 50 | const double epsilon = P.getOptionDoubleValue("-e",0.000000001); 51 | const intE n = GA.n; 52 | const double oneMinusAlphaOverTwo = (1-alpha)/2; 53 | 54 | unordered_map pr; 55 | pr[start] = make_pair(0.0,1.0); //starting vertex 56 | queue q; 57 | q.push(start); 58 | long totalPushes = 0; 59 | while(!q.empty()) { 60 | uintE v = q.front(); 61 | q.pop(); 62 | pairDouble v_pr = pr[v]; 63 | uintE d = GA.V[v].getOutDegree(); 64 | while(v_pr.second > epsilon*d) { 65 | v_pr.first += alpha*v_pr.second; 66 | double old_vr = v_pr.second; 67 | v_pr.second = v_pr.second*oneMinusAlphaOverTwo; 68 | totalPushes++; 69 | for(long i=0;i epsd && oldRes < epsd) { 78 | q.push(ngh); 79 | } 80 | } 81 | } 82 | pr[v] = v_pr; 83 | } 84 | t1.stop(); 85 | pairIF* A = newA(pairIF,pr.size()); 86 | 87 | long numNonzerosQ = 0; 88 | for(auto it = pr.begin(); it != pr.end(); it++) { 89 | if(it->second.first > 0) { 90 | A[numNonzerosQ++] = make_pair(it->first,it->second.first); 91 | } 92 | } 93 | 94 | sweepObject sweep = parSweepCut(GA,A,numNonzerosQ,start); 95 | free(A); 96 | cout << "number of vertices touched = " << pr.size() << endl; 97 | cout << "number of edges touched = " << sweep.vol << endl; 98 | cout << "size of solution = " << numNonzerosQ << endl; 99 | cout << "total pushes = " << totalPushes << endl; 100 | cout << "conductance = " << sweep.conductance << " |S| = " << sweep.sizeS << " vol(S) = " << sweep.volS << " edgesCrossing = " << sweep.edgesCrossing << endl; 101 | t1.reportTotal("computation time"); 102 | } 103 | -------------------------------------------------------------------------------- /apps/localAlg/ACL-Serial-Opt-Naive.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Parallel Local Clustering 2 | // Algorithms". Copyright (c) 2016 Julian Shun 3 | // 4 | // Permission is hereby granted, free of charge, to any person 5 | // obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights (to use, copy, 8 | // modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | // This is a serial implementation of PR-Nibble using the optimized 25 | // update rule and uses a regular queue. Currently only works with 26 | // uncompressed graphs, and not with compressed graphs. 27 | #include "ligra.h" 28 | #include 29 | #include 30 | #include "sweep.h" 31 | using namespace std; 32 | 33 | typedef pair pairDouble; 34 | typedef pair pairIF; 35 | struct pq_compare { bool operator () (pairIF a, pairIF b) { 36 | return a.second > b.second; }}; 37 | 38 | timer t1; 39 | template 40 | void Compute(graph& GA, commandLine P) { 41 | t1.start(); 42 | long start = P.getOptionLongValue("-r",0); 43 | const double alpha = P.getOptionDoubleValue("-a",0.15); 44 | const double epsilon = P.getOptionDoubleValue("-e",0.000000001); 45 | const intE n = GA.n; 46 | const double twoAlphaOverOnePlusAlpha = 2*alpha/(1+alpha); 47 | const double oneMinusAlphaOverOnePlusAlpha = (1-alpha)/(1+alpha); 48 | 49 | unordered_map pr; 50 | pr[start] = make_pair(0.0,1.0); //starting vertex 51 | queue q; 52 | q.push(start); 53 | long totalPushes = 0; 54 | while(!q.empty()) { 55 | totalPushes++; 56 | uintE v = q.front(); 57 | q.pop(); 58 | pairDouble v_pr = pr[v]; 59 | uintE d = GA.V[v].getOutDegree(); 60 | v_pr.first += twoAlphaOverOnePlusAlpha*v_pr.second; 61 | double old_vr = v_pr.second; 62 | v_pr.second = 0; 63 | pr[v] = v_pr; 64 | for(long i=0;i epsd && oldRes < epsd) { 73 | //if previous residual is small, that means it is not in q, so insert it 74 | q.push(ngh); 75 | } 76 | } 77 | } 78 | t1.stop(); 79 | pairIF* A = newA(pairIF,pr.size()); 80 | 81 | long numNonzerosQ = 0; 82 | for(auto it = pr.begin(); it != pr.end(); it++) { 83 | if(it->second.first > 0) { 84 | A[numNonzerosQ++] = make_pair(it->first,it->second.first); 85 | } 86 | } 87 | 88 | sweepObject sweep = sweepCut(GA,A,numNonzerosQ,start); 89 | free(A); 90 | cout << "number of vertices touched = " << pr.size() << endl; 91 | cout << "number of edges touched = " << sweep.vol << endl; 92 | cout << "size of solution = " << numNonzerosQ << endl; 93 | cout << "total pushes = " << totalPushes << endl; 94 | cout << "conductance = " << sweep.conductance << " |S| = " << sweep.sizeS << " vol(S) = " << sweep.volS << " edgesCrossing = " << sweep.edgesCrossing << endl; 95 | t1.reportTotal("computation time"); 96 | } 97 | -------------------------------------------------------------------------------- /apps/localAlg/ACL-Serial-Opt.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Parallel Local Clustering 2 | // Algorithms". Copyright (c) 2016 Julian Shun 3 | // 4 | // Permission is hereby granted, free of charge, to any person 5 | // obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights (to use, copy, 8 | // modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | // This is a serial implementation of PR-Nibble using the optimized 25 | // update rule and uses a priority queue. Currently only works with 26 | // uncompressed graphs, and not with compressed graphs. 27 | #include "ligra.h" 28 | #include 29 | #include 30 | #include "sweep.h" 31 | using namespace std; 32 | 33 | typedef pair pairDouble; 34 | typedef pair pairIF; 35 | struct pq_compare { bool operator () (pairIF a, pairIF b) { 36 | return a.second > b.second; }}; 37 | 38 | timer t1; 39 | template 40 | void Compute(graph& GA, commandLine P) { 41 | t1.start(); 42 | long start = P.getOptionLongValue("-r",0); 43 | if(GA.V[start].getOutDegree() == 0) { 44 | cout << "starting vertex has degree 0" << endl; 45 | return; 46 | } 47 | const double alpha = P.getOptionDoubleValue("-a",0.15); 48 | const double epsilon = P.getOptionDoubleValue("-e",0.000000001); 49 | const intE n = GA.n; 50 | const double twoAlphaOverOnePlusAlpha = 2*alpha/(1+alpha); 51 | const double oneMinusAlphaOverOnePlusAlpha = (1-alpha)/(1+alpha); 52 | 53 | unordered_map pr; 54 | pr[start] = make_pair(0.0,1.0); //starting vertex 55 | multiset q; 56 | q.insert(make_pair(start,1.0)); 57 | long totalPushes = 0; 58 | while(!q.empty()) { 59 | totalPushes++; 60 | pairIF top = *q.begin(); 61 | uintE v = top.first; 62 | q.erase(q.begin()); 63 | pairDouble v_pr = pr[v]; 64 | uintE d = GA.V[v].getOutDegree(); 65 | v_pr.first += twoAlphaOverOnePlusAlpha*v_pr.second; 66 | double old_vr = v_pr.second; 67 | v_pr.second = 0; 68 | pr[v] = v_pr; 69 | for(long i=0;i epsd && oldRes < epsd) { 78 | //if previous residual is small, that means it is not in q, so insert it 79 | q.insert(make_pair(ngh,ngh_pr.second/ngh_d)); 80 | } 81 | } 82 | } 83 | t1.stop(); 84 | pairIF* A = newA(pairIF,pr.size()); 85 | 86 | long numNonzerosQ = 0; 87 | for(auto it = pr.begin(); it != pr.end(); it++) { 88 | if(it->second.first > 0) { 89 | A[numNonzerosQ++] = make_pair(it->first,it->second.first); 90 | } 91 | } 92 | 93 | sweepObject sweep = parSweepCut(GA,A,numNonzerosQ,start); 94 | free(A); 95 | cout << "number of vertices touched = " << pr.size() << endl; 96 | cout << "number of edges touched = " << sweep.vol << endl; 97 | cout << "size of solution = " << numNonzerosQ << endl; 98 | cout << "total pushes = " << totalPushes << endl; 99 | cout << "conductance = " << sweep.conductance << " |S| = " << sweep.sizeS << " vol(S) = " << sweep.volS << " edgesCrossing = " << sweep.edgesCrossing << endl; 100 | t1.reportTotal("computation time"); 101 | } 102 | -------------------------------------------------------------------------------- /apps/localAlg/ACL-Serial.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Parallel Local Clustering 2 | // Algorithms". Copyright (c) 2016 Julian Shun 3 | // 4 | // Permission is hereby granted, free of charge, to any person 5 | // obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights (to use, copy, 8 | // modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | // This is a serial implementation of PR-Nibble, the approximate 25 | // PageRank algorithm in "Local Graph Partitioning using PageRank 26 | // Vectors" by Reid Andersen, Fan Chung and Kevin Lang, FOCS 2006. It 27 | // uses a priority queue to store vertices. Currently only works with 28 | // uncompressed graphs, and not with compressed graphs. 29 | #include "ligra.h" 30 | #include 31 | #include 32 | #include "sweep.h" 33 | using namespace std; 34 | 35 | typedef pair pairDouble; 36 | typedef pair pairIF; 37 | struct pq_compare { bool operator () (pairIF a, pairIF b) { 38 | return a.second > b.second; }}; 39 | 40 | timer t1; 41 | template 42 | void Compute(graph& GA, commandLine P) { 43 | t1.start(); 44 | long start = P.getOptionLongValue("-r",0); 45 | if(GA.V[start].getOutDegree() == 0) { 46 | cout << "starting vertex has degree 0" << endl; 47 | return; 48 | } 49 | const double alpha = P.getOptionDoubleValue("-a",0.15); 50 | const double epsilon = P.getOptionDoubleValue("-e",0.000000001); 51 | const intE n = GA.n; 52 | const double oneMinusAlphaOverTwo = (1-alpha)/2; 53 | 54 | unordered_map pr; 55 | pr[start] = make_pair(0.0,1.0); //starting vertex 56 | multiset q; 57 | q.insert(make_pair(start,1.0)); 58 | long totalPushes = 0; 59 | while(!q.empty()) { 60 | pairIF top = *q.begin(); 61 | uintE v = top.first; 62 | q.erase(q.begin()); 63 | pairDouble v_pr = pr[v]; 64 | uintE d = GA.V[v].getOutDegree(); 65 | while(v_pr.second > epsilon*d) { 66 | v_pr.first += alpha*v_pr.second; 67 | double old_vr = v_pr.second; 68 | v_pr.second = v_pr.second*oneMinusAlphaOverTwo; 69 | totalPushes++; 70 | for(long i=0;i epsd && oldRes < epsd) { 79 | q.insert(make_pair(ngh,ngh_pr.second/ngh_d)); 80 | } 81 | } 82 | } 83 | pr[v] = v_pr; 84 | } 85 | t1.stop(); 86 | pairIF* A = newA(pairIF,pr.size()); 87 | 88 | long numNonzerosQ = 0; 89 | for(auto it = pr.begin(); it != pr.end(); it++) { 90 | if(it->second.first > 0) { 91 | A[numNonzerosQ++] = make_pair(it->first,it->second.first); 92 | } 93 | } 94 | 95 | sweepObject sweep = parSweepCut(GA,A,numNonzerosQ,start); 96 | free(A); 97 | cout << "number of vertices touched = " << pr.size() << endl; 98 | cout << "number of edges touched = " << sweep.vol << endl; 99 | cout << "size of solution = " << numNonzerosQ << endl; 100 | cout << "total pushes = " << totalPushes << endl; 101 | cout << "conductance = " << sweep.conductance << " |S| = " << sweep.sizeS << " vol(S) = " << sweep.volS << " edgesCrossing = " << sweep.edgesCrossing << endl; 102 | t1.reportTotal("computation time"); 103 | } 104 | -------------------------------------------------------------------------------- /apps/localAlg/HeatKernel-Randomized-Parallel.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Parallel Local Clustering 2 | // Algorithms". Copyright (c) 2016 Julian Shun 3 | // 4 | // Permission is hereby granted, free of charge, to any person 5 | // obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights (to use, copy, 8 | // modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | // 24 | // This is a parallel implementation of the heat kernel PageRank 25 | // algorithm rand-HK-PR. Currently only works with uncompressed 26 | // graphs, and not with compressed graphs. 27 | #include "ligra.h" 28 | #include "sweep.h" 29 | #include "sampleSort.h" 30 | using namespace std; 31 | 32 | typedef pair ACLpair; 33 | 34 | struct intLT { bool operator () (uintT a, uintT b) { return a < b; }; }; 35 | 36 | struct notMax { bool operator () (uintE a) { return a != UINT_E_MAX; }}; 37 | 38 | //1/2 probability of staying, 1/2d probability of going to each neighbor 39 | template 40 | inline uintE walk(uintE x, vertex* V, uintE seed) { 41 | uintE d = V[x].getOutDegree(); 42 | uintE randInt = hashInt(seed) % d; 43 | return V[x].getOutNeighbor(randInt); 44 | } 45 | 46 | timer t1; 47 | template 48 | void Compute(graph& GA, commandLine P) { 49 | t1.start(); 50 | const int procs = P.getOptionIntValue("-p",0); 51 | if(procs > 0) setWorkers(procs); 52 | long start = P.getOptionLongValue("-r",0); 53 | if(GA.V[start].getOutDegree() == 0) { 54 | cout << "starting vertex has degree 0" << endl; 55 | return; 56 | } 57 | const uintE K = P.getOptionIntValue("-K",10); 58 | const uintE N = P.getOptionIntValue("-N",10); 59 | const double t = P.getOptionDoubleValue("-t",3); 60 | srand (time(NULL)); 61 | uintE seed = rand(); 62 | const intE n = GA.n; 63 | 64 | //walk length probabilities 65 | double* fact = newA(double,K); 66 | fact[0] = 1; 67 | for(long k=1;k 31 | #include 32 | #include "sweep.h" 33 | using namespace std; 34 | 35 | //1/2 probability of staying, 1/2d probability of going to each neighbor 36 | template 37 | inline uintE walk(uintE x, vertex* V, uintE seed) { 38 | uintE d = V[x].getOutDegree(); 39 | uintE randInt = hashInt(seed) % d; 40 | return V[x].getOutNeighbor(randInt); 41 | } 42 | 43 | typedef pair pairIF; 44 | 45 | timer t1; 46 | template 47 | void Compute(graph& GA, commandLine P) { 48 | t1.start(); 49 | long start = P.getOptionLongValue("-r",0); 50 | if(GA.V[start].getOutDegree() == 0) { 51 | cout << "starting vertex has degree 0" << endl; 52 | return; 53 | } 54 | const uintE K = P.getOptionIntValue("-K",10); 55 | const uintE N = P.getOptionIntValue("-N",10); 56 | const double t = P.getOptionDoubleValue("-t",3); 57 | srand (time(NULL)); 58 | uintE seed = rand(); 59 | const intE n = GA.n; 60 | 61 | //walk length probabilities 62 | double* fact = newA(double,K); 63 | fact[0] = 1; 64 | for(long k=1;k p; 69 | for(long i=0;ifirst] /= N; 84 | } 85 | 86 | free(probs); free(fact); 87 | t1.stop(); 88 | pairIF* A = newA(pairIF,p.size()); 89 | 90 | long numNonzerosQ = 0; 91 | for(auto it = p.begin(); it != p.end(); it++) { 92 | A[numNonzerosQ++] = make_pair(it->first,it->second); 93 | } 94 | sweepObject sweep = sweepCut(GA,A,numNonzerosQ,start); 95 | free(A); 96 | cout << "number of vertices touched = " << p.size() << endl; 97 | cout << "number of edges touched = " << sweep.vol << endl; 98 | cout << "conductance = " << sweep.conductance << " |S| = " << sweep.sizeS << " vol(S) = " << sweep.volS << " edgesCrossing = " << sweep.edgesCrossing << endl; 99 | t1.reportTotal("computation time"); 100 | } 101 | -------------------------------------------------------------------------------- /apps/localAlg/HeatKernel-Serial.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Parallel Local Clustering 2 | // Algorithms". Copyright (c) 2016 Julian Shun 3 | // 4 | // Permission is hereby granted, free of charge, to any person 5 | // obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights (to use, copy, 8 | // modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | // This is a serial implementation of the HeatKernel PageRank 25 | // algorithm (HK-PR) in "Heat Kernel Based Community Detection" by 26 | // Kyle Kloster and David Gleich, KDD 2014. Currently only works with 27 | // uncompressed graphs, and not with compressed graphs. 28 | #include "ligra.h" 29 | #include 30 | #include 31 | #include "sweep.h" 32 | using namespace std; 33 | 34 | typedef pair pairDouble; 35 | typedef pair pairIF; 36 | typedef pair pairInt; 37 | 38 | class hashPair { 39 | public: 40 | size_t operator () (const intPair &x) const { 41 | return hashInt(x.first)*31+hashInt(x.second); 42 | }}; 43 | 44 | class equalPair { 45 | public: 46 | bool operator () (const intPair &a, const intPair &b) const { 47 | return a.first == b.first && a.second == b.second; 48 | }}; 49 | 50 | timer t1; 51 | template 52 | void Compute(graph& GA, commandLine P) { 53 | t1.start(); 54 | long start = P.getOptionLongValue("-r",0); 55 | if(GA.V[start].getOutDegree() == 0) { 56 | cout << "starting vertex has degree 0" << endl; 57 | return; 58 | } 59 | const double t = P.getOptionDoubleValue("-t",3); 60 | const double epsilon = P.getOptionDoubleValue("-e",0.000000001); 61 | const uintE N = P.getOptionIntValue("-N",1); 62 | const intE n = GA.n; 63 | const double constant = exp(t)*epsilon/(2*(double)N); 64 | double* psis = newA(double,N); 65 | double* fact = newA(double,N); 66 | fact[0] = 1; 67 | for(long k=1;k x; 77 | unordered_map r; 78 | r[make_pair(start,0)] = 1.0; //starting vertex 79 | queue q; 80 | q.push(make_pair(start,0)); 81 | long totalPushes = 0; 82 | while(!q.empty()) { 83 | pairInt vj = q.front(); 84 | uintE v = vj.first, j = vj.second; 85 | q.pop(); 86 | double rvj = r[vj]; 87 | x[v] += rvj; 88 | //r[vj] = 0; 89 | uintE d = GA.V[v].getOutDegree(); 90 | double mass = t*rvj/((double)(j+1)*d); 91 | totalPushes++; 92 | for(long i=0;i= thresh) 98 | q.push(next); 99 | r[next] += mass; 100 | } 101 | } 102 | free(psis); free(fact); free(tm); 103 | t1.stop(); 104 | pairIF* A = newA(pairIF,x.size()); 105 | 106 | long numNonzerosQ = 0; 107 | for(auto it = x.begin(); it != x.end(); it++) { 108 | A[numNonzerosQ++] = make_pair(it->first,it->second); 109 | } 110 | sweepObject sweep = sweepCut(GA,A,numNonzerosQ,start); 111 | free(A); 112 | cout << "number of vertices touched = " << x.size() << endl; 113 | cout << "number of edges touched = " << sweep.vol << endl; 114 | cout << "total pushes = " << totalPushes << endl; 115 | cout << "conductance = " << sweep.conductance << " |S| = " << sweep.sizeS << " vol(S) = " << sweep.volS << " edgesCrossing = " << sweep.edgesCrossing << endl; 116 | t1.reportTotal("computation time"); 117 | } 118 | -------------------------------------------------------------------------------- /apps/localAlg/Makefile: -------------------------------------------------------------------------------- 1 | ifdef LONG 2 | INTT = -DLONG 3 | endif 4 | 5 | ifdef EDGELONG 6 | INTE = -DEDGELONG 7 | endif 8 | 9 | #compilers 10 | ifdef CILK 11 | PCC = g++ 12 | PCFLAGS = -std=c++14 -fcilkplus -lcilkrts -O3 -DCILK $(INTT) $(INTE) 13 | PLFLAGS = -fcilkplus -lcilkrts 14 | 15 | else ifdef MKLROOT 16 | PCC = icpc 17 | PCFLAGS = -std=c++14 -O3 -DCILKP $(INTT) $(INTE) 18 | 19 | else ifdef OPENMP 20 | PCC = g++ 21 | PCFLAGS = -std=c++14 -fopenmp -march=native -O3 -DOPENMP $(INTT) $(INTE) 22 | 23 | else 24 | PCC = g++ 25 | PCFLAGS = -std=c++14 -O3 $(INTT) $(INTE) 26 | endif 27 | 28 | COMMON= ligra.h graph.h compressedVertex.h vertex.h utils.h IO.h parallel.h gettime.h index_map.h maybe.h sequence.h edgeMap_utils.h binary_search.h quickSort.h parseCommandLine.h byte.h byteRLE.h nibble.h byte-pd.h byteRLE-pd.h nibble-pd.h vertexSubset.h encoder.C 29 | LOCAL_COMMON = sweep.h sparseSet.h sampleSort.h 30 | INTSORT= blockRadixSort.h transpose.h 31 | SERIAL = ACL-Serial ACL-Serial-Naive ACL-Serial-Opt ACL-Serial-Opt-Naive HeatKernel-Serial HeatKernel-Randomized-Serial Nibble-Serial 32 | PARALLEL = ACL-Sync-Local ACL-Sync-Local-Opt HeatKernel-Parallel HeatKernel-Randomized-Parallel Nibble-Parallel 33 | 34 | all: $(SERIAL) $(PARALLEL) 35 | 36 | ser: $(SERIAL) 37 | 38 | par: $(PARALLEL) 39 | 40 | % : %.C $(COMMON) $(LOCAL_COMMON) $(INTSORT) 41 | $(PCC) $(PCFLAGS) -o $@ $< 42 | 43 | $(COMMON): 44 | ln -s ../../ligra/$@ . 45 | 46 | $(INTSORT): 47 | ln -s ../../utils/$@ . 48 | 49 | .PHONY : clean 50 | 51 | clean : 52 | rm -f *.o $(SERIAL) $(PARALLEL) 53 | 54 | cleansrc : 55 | rm -f *.o $(SERIAL) $(PARALLEL) 56 | rm $(COMMON) $(INTSORT) 57 | -------------------------------------------------------------------------------- /apps/localAlg/Nibble-Serial.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Parallel Local Clustering 2 | // Algorithms". Copyright (c) 2016 Julian Shun 3 | // 4 | // Permission is hereby granted, free of charge, to any person 5 | // obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights (to use, copy, 8 | // modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | // This is a serial implementation of the Nibble algorithm in "A Local 25 | // Clustering Algorithm for Massive Graphs and its Application to 26 | // Nearly Linear Time Graph Partitioning" by Daniel Spielman and 27 | // Shang-Hua Teng, Siam J. Comput. 2013. Currently only works with 28 | // uncompressed graphs, and not with compressed graphs. 29 | #include "ligra.h" 30 | #include 31 | #include "sweep.h" 32 | using namespace std; 33 | 34 | typedef pair pairDouble; 35 | typedef pair pairIF; 36 | 37 | timer t1; 38 | template 39 | void Compute(graph& GA, commandLine P) { 40 | t1.start(); 41 | long start = P.getOptionLongValue("-r",0); 42 | if(GA.V[start].getOutDegree() == 0) { 43 | cout << "starting vertex has degree 0" << endl; 44 | return; 45 | } 46 | const double epsilon = P.getOptionDoubleValue("-e",0.000000001); 47 | const long T = P.getOptionLongValue("-T",10); 48 | const intE n = GA.n; 49 | 50 | unordered_map q; 51 | q[start] = 1.0; //starting vertex 52 | long totalPushes = 0; 53 | 54 | for(long i=0;i q_next; 56 | for(auto it=q.begin();it!=q.end();it++) { 57 | uintE v = it->first; 58 | double q = it->second; 59 | uintE d = GA.V[v].getOutDegree(); 60 | if(q > d*epsilon) { 61 | totalPushes++; 62 | q_next[v] += q/2; 63 | double nghMass = q/(2*d); 64 | for(long j=0;jfirst,it->second); 80 | } 81 | 82 | sweepObject sweep = sweepCut(GA,A,numNonzerosQ,start); 83 | free(A); 84 | cout << "number of vertices touched = " << q.size() << endl; 85 | cout << "number of edges touched = " << sweep.vol << endl; 86 | cout << "total pushes = " << totalPushes << endl; 87 | cout << "conductance = " << sweep.conductance << " |S| = " << sweep.sizeS << " vol(S) = " << sweep.volS << " edgesCrossing = " << sweep.edgesCrossing << endl; 88 | t1.reportTotal("computation time"); 89 | } 90 | -------------------------------------------------------------------------------- /apps/localAlg/sampleSort.h: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2010 Guy Blelloch and Harsha Vardhan Simhadri and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #ifndef SAMPLE_SORT_H 23 | #define SAMPLE_SORT_H 24 | #include 25 | #include 26 | #include "parallel.h" 27 | #include "utils.h" 28 | #include "gettime.h" 29 | #include "math.h" 30 | #include "quickSort.h" 31 | #include "transpose.h" 32 | 33 | template 34 | void mergeSeq (E* sA, E* sB, intT* sC, intT lA, intT lB, BinPred f) { 35 | if (lA==0 || lB==0) return; 36 | E *eA = sA+lA; 37 | E *eB = sB+lB; 38 | for (intT i=0; i <= lB; i++) sC[i] = 0; 39 | while(1) { 40 | while (f(*sA, *sB)) {(*sC)++; if (++sA == eA) return;} 41 | sB++; sC++; 42 | if (sB == eB) break; 43 | if (!(f(*(sB-1),*sB))) { 44 | while (!f(*sB, *sA)) {(*sC)++; if (++sA == eA) return;} 45 | sB++; sC++; 46 | if (sB == eB) break; 47 | } 48 | } 49 | *sC = eA-sA; 50 | } 51 | 52 | #define SSORT_THR 100000 53 | #define AVG_SEG_SIZE 2 54 | #define PIVOT_QUOT 2 55 | 56 | template 57 | void sampleSort (E* A, intT n, BinPred f) { 58 | if (n < SSORT_THR) quickSort(A, n, f); 59 | else { 60 | intT sq = (intT)(pow(n,0.5)); 61 | intT rowSize = sq*AVG_SEG_SIZE; 62 | intT numR = (intT)ceil(((double)n)/((double)rowSize)); 63 | intT numSegs = (sq-1)/PIVOT_QUOT; 64 | int overSample = 4; 65 | intT sampleSetSize = numSegs*overSample; 66 | E* sampleSet = newA(E,sampleSetSize); 67 | //cout << "n=" << n << " num_segs=" << numSegs << endl; 68 | 69 | // generate samples with oversampling 70 | parallel_for (intT j=0; j< sampleSetSize; ++j) { 71 | intT o = hashInt((uintT)j)%n; 72 | sampleSet[j] = A[o]; 73 | } 74 | 75 | // sort the samples 76 | quickSort(sampleSet, sampleSetSize, f); 77 | 78 | // subselect samples at even stride 79 | E* pivots = newA(E,numSegs-1); 80 | parallel_for (intT k=0; k < numSegs-1; ++k) { 81 | intT o = overSample*k; 82 | pivots[k] = sampleSet[o]; 83 | } 84 | free(sampleSet); 85 | //nextTime("samples"); 86 | 87 | E *B = newA(E, numR*rowSize); 88 | intT *segSizes = newA(intT, numR*numSegs); 89 | intT *offsetA = newA(intT, numR*numSegs); 90 | intT *offsetB = newA(intT, numR*numSegs); 91 | 92 | // sort each row and merge with samples to get counts 93 | parallel_for (intT r = 0; r < numR; ++r) { 94 | intT offset = r * rowSize; 95 | intT size = (r < numR - 1) ? rowSize : n - offset; 96 | sampleSort(A+offset, size, f); 97 | mergeSeq(A + offset, pivots, segSizes + r*numSegs, size, numSegs-1, f); 98 | } 99 | //nextTime("sort and merge"); 100 | 101 | // transpose from rows to columns 102 | sequence::scan(segSizes, offsetA, numR*numSegs, plus(),(intT)0); 103 | transpose(segSizes, offsetB).trans(numR, numSegs); 104 | sequence::scan(offsetB, offsetB, numR*numSegs, plus(),(intT)0); 105 | blockTrans(A, B, offsetA, offsetB, segSizes).trans(numR, numSegs); 106 | {parallel_for (intT i=0; i < n; ++i) A[i] = B[i];} 107 | //nextTime("transpose"); 108 | 109 | free(B); free(offsetA); free(segSizes); 110 | 111 | // sort the columns 112 | {parallel_for (intT i=0; i 4 | 5 | namespace pbbs { 6 | // the following parameter can be tuned 7 | constexpr const size_t _binary_search_base = 16; 8 | 9 | template 10 | size_t linear_search(Sequence I, typename Sequence::T v, const F& less) { 11 | for (size_t i = 0; i < I.size(); i++) 12 | if (!less(I[i],v)) return i; 13 | return I.size(); 14 | } 15 | 16 | // return index to first key greater or equal to v 17 | template 18 | size_t binary_search(Sequence I, typename Sequence::T v, const F& less) { 19 | size_t start = 0; 20 | size_t end = I.size(); 21 | while (end-start > _binary_search_base) { 22 | size_t mid = (end+start)/2; 23 | if (!less(I[mid],v)) end = mid; 24 | else start = mid + 1; 25 | } 26 | return start + linear_search(I.slice(start,end),v,less); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ligra/decoder.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Smaller and Faster: Parallel 2 | // Processing of Compressed Graphs with Ligra+", presented at the IEEE 3 | // Data Compression Conference, 2015. 4 | // Copyright (c) 2015 Julian Shun, Laxman Dhulipala and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | //include the code for the desired compression scheme 26 | #ifndef PD 27 | #ifdef BYTE 28 | #include "byte.h" 29 | #elif defined NIBBLE 30 | #include "nibble.h" 31 | #else 32 | #include "byteRLE.h" 33 | #endif 34 | #else //decode in parallel 35 | #ifdef BYTE 36 | #include "byte-pd.h" 37 | #elif defined NIBBLE 38 | #include "nibble-pd.h" 39 | #else 40 | #include "byteRLE-pd.h" 41 | #endif 42 | #endif 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include "parallel.h" 49 | #include "utils.h" 50 | #include "graph.h" 51 | #include "parseCommandLine.h" 52 | #include "IO.h" 53 | using namespace std; 54 | 55 | struct printAdjT { 56 | stringstream* ss; 57 | printAdjT(stringstream *_ss) : ss(_ss) {} 58 | bool srcTarg(uintE src, uintE target, uintT edgeNumber) { 59 | *ss << target << endl; 60 | return true; 61 | } 62 | bool srcTarg(uintE src, uintE target, intE weight, uintT edgeNumber) { 63 | *ss << target << endl; 64 | return true; 65 | } 66 | }; 67 | 68 | struct printWghT { 69 | stringstream* ss; 70 | printWghT(stringstream *_ss) : ss(_ss) {} 71 | bool srcTarg(uintE src, uintE target, intE weight, uintT edgeNumber) { 72 | *ss << weight << endl; 73 | return true; 74 | } 75 | }; 76 | 77 | void writeAdjGraph(graph G, ofstream *of, bool weighted) { 78 | compressedSymmetricVertex *V = G.V; 79 | for (long i = 0; i < G.n; i++) { 80 | stringstream ss; 81 | uchar *nghArr = V[i].getOutNeighbors(); 82 | uintT d = V[i].getOutDegree(); 83 | if(weighted) 84 | decodeWgh(printAdjT(&ss), nghArr, i, d); 85 | else 86 | decode(printAdjT(&ss), nghArr, i, d); 87 | *of << ss.str(); 88 | } 89 | if(weighted) { 90 | cout << "writing weights..." << endl; 91 | for (long i = 0; i < G.n; i++) { 92 | stringstream ss; 93 | uchar *nghArr = V[i].getOutNeighbors(); 94 | uintT d = V[i].getOutDegree(); 95 | decodeWgh(printWghT(&ss), nghArr, i, d); 96 | *of << ss.str(); 97 | } 98 | } 99 | } 100 | 101 | //Converts binary compressed graph to text format. For weighted 102 | //graphs, pass the "-w" flag. Note that if the original graph 103 | //contained self-edges or duplicate edges, these would have been 104 | //deleted by the encoder and will not be recreated by the decoder. 105 | int parallel_main(int argc, char* argv[]) { 106 | commandLine P(argc,argv,"[-w] "); 107 | char* iFile = P.getArgument(1); 108 | char* oFile = P.getArgument(0); 109 | bool weighted = P.getOptionValue("-w"); 110 | graph G = readCompressedGraph(iFile,1,0); 111 | long n = G.n, m = G.m; 112 | 113 | ofstream out(oFile,ofstream::out); 114 | if(weighted) out << "WeightedAdjacencyGraph\n" << n << endl << m << endl; 115 | else out << "AdjacencyGraph\n" << n << endl << m << endl; 116 | cout<<"writing offsets..."< 8 | struct dyn_arr { 9 | E* A; 10 | size_t size; 11 | size_t capacity; 12 | bool alloc; 13 | 14 | dyn_arr() : A(NULL), size(0), capacity(0), alloc(false) {} 15 | dyn_arr(size_t s) : size(0), capacity(s), alloc(true) { A = newA(E, s); } 16 | dyn_arr(E* _A, long _size, long _capacity, bool _alloc) : 17 | A(_A), size(_size), capacity(_capacity), alloc(_alloc) {} 18 | 19 | void del() { 20 | if (alloc) { 21 | free(A); 22 | alloc = false; 23 | } 24 | } 25 | 26 | void clear() { size = 0; } 27 | 28 | inline void resize(size_t n) { 29 | if (n + size > capacity) { 30 | size_t new_capacity = max(2*(n + size), (size_t)MIN_BKT_SIZE); 31 | E* nA = newA(E, new_capacity); 32 | granular_for(i, 0, size, 2000, nA[i] = A[i];); 33 | if (alloc) { 34 | free(A); 35 | } 36 | A = nA; 37 | capacity = new_capacity; 38 | alloc = true; 39 | } 40 | } 41 | 42 | inline void insert(E val, size_t pos) { 43 | A[size + pos] = val; 44 | } 45 | 46 | template 47 | inline void copyIn(F f, size_t n) { 48 | resize(n); 49 | granular_for(i, 0, n, 2000, A[size + i] = f[i];); 50 | size += n; 51 | } 52 | 53 | template 54 | inline void copyInF(F f, size_t n) { 55 | resize(n); 56 | granular_for(i, 0, n, 2000, A[size + i] = f(i);); 57 | size += n; 58 | } 59 | 60 | }; 61 | 62 | 63 | -------------------------------------------------------------------------------- /ligra/edgeMapReduce.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ligra.h" 4 | #include "histogram.h" 5 | 6 | // edgeMapInduced 7 | // Version of edgeMapSparse that maps over the one-hop frontier and returns it as 8 | // a sparse array, without filtering. 9 | template 10 | inline vertexSubsetData edgeMapInduced(graph& GA, VS& V, F& f) { 11 | vertex *G = GA.V; 12 | uintT m = V.size(); 13 | V.toSparse(); 14 | auto degrees = array_imap(m); 15 | granular_for(i, 0, m, (m > 2000), { 16 | vertex v = G[V.vtx(i)]; 17 | uintE degree = v.getOutDegree(); 18 | degrees[i] = degree; 19 | }); 20 | long outEdgeCount = pbbs::scan_add(degrees, degrees); 21 | if (outEdgeCount == 0) { 22 | return vertexSubsetData(GA.n); 23 | } 24 | typedef tuple VE; 25 | VE* outEdges = pbbs::new_array_no_init(outEdgeCount); 26 | 27 | auto gen = [&] (const uintE& ngh, const uintE& offset, const Maybe& val = Maybe()) { 28 | outEdges[offset] = make_tuple(ngh, val.t); 29 | }; 30 | 31 | parallel_for (size_t i = 0; i < m; i++) { 32 | uintT o = degrees[i]; 33 | auto v = V.vtx(i); 34 | G[v].template copyOutNgh(v, o, f, gen); 35 | } 36 | auto vs = vertexSubsetData(GA.n, outEdgeCount, outEdges); 37 | return vs; 38 | } 39 | 40 | template 41 | struct EdgeMap { 42 | using K = uintE; // keys are always uintE's (vertex-identifiers) 43 | using KV = tuple; 44 | graph& G; 45 | pbbs::hist_table ht; 46 | 47 | EdgeMap(graph& _G, KV _empty, size_t ht_size=numeric_limits::max()) : G(_G) { 48 | if (ht_size == numeric_limits::max()) { 49 | ht_size = 1L << pbbs::log2_up(G.m/20); 50 | } else { ht_size = 1L << pbbs::log2_up(ht_size); } 51 | ht = pbbs::hist_table(_empty, ht_size); 52 | } 53 | 54 | // map_f: (uintE v, uintE ngh) -> E 55 | // reduce_f: (E, tuple(uintE ngh, E ngh_val)) -> E 56 | // apply_f: (uintE ngh, E reduced_val) -> O 57 | template 58 | inline vertexSubsetData edgeMapReduce(VS& vs, Map& map_f, Reduce& reduce_f, Apply& apply_f) { 59 | size_t m = vs.size(); 60 | if (m == 0) { 61 | return vertexSubsetData(vs.numNonzeros()); 62 | } 63 | 64 | auto oneHop = edgeMapInduced(G, vs, map_f); 65 | oneHop.toSparse(); 66 | 67 | auto get_elm = make_in_imap >(oneHop.size(), [&] (size_t i) { return oneHop.vtxAndData(i); }); 68 | auto get_key = make_in_imap(oneHop.size(), [&] (size_t i) -> uintE { return oneHop.vtx(i); }); 69 | 70 | auto q = [&] (sequentialHT& S, tuple v) -> void { S.template insertF(v, reduce_f); }; 71 | auto res = pbbs::histogram_reduce, tuple >(get_elm, get_key, oneHop.size(), q, apply_f, ht); 72 | oneHop.del(); 73 | return vertexSubsetData(vs.numNonzeros(), res.first, res.second); 74 | } 75 | 76 | template 77 | inline vertexSubsetData edgeMapCount(VS& vs, Apply& apply_f) { 78 | auto map_f = [] (const uintE& i, const uintE& j) { return pbbs::empty(); }; 79 | auto reduce_f = [&] (const uintE& cur, const tuple& r) { return cur + 1; }; 80 | return edgeMapReduce(vs, map_f, reduce_f, apply_f); 81 | } 82 | 83 | ~EdgeMap() { 84 | ht.del(); 85 | } 86 | }; 87 | -------------------------------------------------------------------------------- /ligra/edgeMap_utils.h: -------------------------------------------------------------------------------- 1 | // Contains helper functions and special cases of edgeMap. Most of these 2 | // functions are specialized for the type of data written per vertex using tools 3 | // from type_traits. 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #include "binary_search.h" 10 | 11 | // Standard version of edgeMapDense. 12 | template ::value, int>::type=0 > 14 | auto get_emdense_gen(tuple* next) { 15 | return [next] (uintE ngh, bool m=false) { 16 | if (m) next[ngh] = make_tuple(1, pbbs::empty()); }; 17 | } 18 | 19 | template ::value, int>::type=0 > 21 | auto get_emdense_gen(tuple* next) { 22 | return [next] (uintE ngh, Maybe m=Maybe()) { 23 | if (m.exists) next[ngh] = make_tuple(1, m.t); }; 24 | } 25 | 26 | // Standard version of edgeMapDenseForward. 27 | template ::value, int>::type=0 > 29 | auto get_emdense_forward_gen(tuple* next) { 30 | return [next] (uintE ngh, bool m=false) { 31 | if (m) next[ngh] = make_tuple(1, pbbs::empty()); }; 32 | } 33 | 34 | template ::value, int>::type=0 > 36 | auto get_emdense_forward_gen(tuple* next) { 37 | return [next] (uintE ngh, Maybe m=Maybe()) { 38 | if (m.exists) next[ngh] = make_tuple(1, m.t); }; 39 | } 40 | 41 | // Standard version of edgeMapSparse. 42 | template ::value, int>::type=0 > 44 | auto get_emsparse_gen(tuple* outEdges) { 45 | return [outEdges] (uintE ngh, uintT offset, bool m=false) { 46 | if (m) { 47 | outEdges[offset] = make_tuple(ngh, pbbs::empty()); 48 | } else { 49 | outEdges[offset] = make_tuple(UINT_E_MAX, pbbs::empty()); 50 | } 51 | }; 52 | } 53 | 54 | template ::value, int>::type=0 > 56 | auto get_emsparse_gen(tuple* outEdges) { 57 | return [outEdges] (uintE ngh, uintT offset, Maybe m=Maybe()) { 58 | if (m.exists) { 59 | outEdges[offset] = make_tuple(ngh, m.t); 60 | } else { 61 | std::get<0>(outEdges[offset]) = UINT_E_MAX; 62 | } 63 | }; 64 | } 65 | 66 | // edgeMapSparse_no_filter 67 | // Version of edgeMapSparse that binary-searches and packs out blocks of the 68 | // next frontier. 69 | template ::value, int>::type=0 > 71 | auto get_emsparse_no_filter_gen(tuple* outEdges) { 72 | return [outEdges] (uintE ngh, uintT offset, bool m=false) { 73 | if (m) { 74 | outEdges[offset] = make_tuple(ngh, pbbs::empty()); 75 | return true; 76 | } 77 | return false; 78 | }; 79 | } 80 | 81 | template ::value, int>::type=0 > 83 | auto get_emsparse_no_filter_gen(tuple* outEdges) { 84 | return [outEdges] (uintE ngh, uintT offset, Maybe m=Maybe()) { 85 | if (m.exists) { 86 | outEdges[offset] = make_tuple(ngh, m.t); 87 | return true; 88 | } 89 | return false; 90 | }; 91 | } 92 | 93 | 94 | 95 | 96 | // Gen-functions that produce no output 97 | template ::value, int>::type=0 > 99 | auto get_emsparse_nooutput_gen() { 100 | return [&] (uintE ngh, uintT offset, bool m=false) { }; 101 | } 102 | 103 | template ::value, int>::type=0 > 105 | auto get_emsparse_nooutput_gen() { 106 | return [&] (uintE ngh, uintT offset, Maybe m=Maybe()) { }; 107 | } 108 | 109 | template ::value, int>::type=0 > 111 | auto get_emdense_nooutput_gen() { 112 | return [&] (uintE ngh, bool m=false) { }; 113 | } 114 | 115 | template ::value, int>::type=0 > 117 | auto get_emdense_nooutput_gen() { 118 | return [&] (uintE ngh, Maybe m=Maybe()) { }; 119 | } 120 | 121 | template ::value, int>::type=0 > 123 | auto get_emdense_forward_nooutput_gen() { 124 | return [&] (uintE ngh, bool m=false) { }; 125 | } 126 | 127 | template ::value, int>::type=0 > 129 | auto get_emdense_forward_nooutput_gen() { 130 | return [&] (uintE ngh, Maybe m=Maybe()) { }; 131 | } 132 | -------------------------------------------------------------------------------- /ligra/gettime.h: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2013 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #ifndef _BENCH_GETTIME_INCLUDED 23 | #define _BENCH_GETTIME_INCLUDED 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | struct timer { 31 | double totalTime; 32 | double lastTime; 33 | double totalWeight; 34 | bool on; 35 | struct timezone tzp; 36 | timer() { 37 | struct timezone tz = {0, 0}; 38 | totalTime=0.0; 39 | totalWeight=0.0; 40 | on=0; tzp = tz;} 41 | double getTime() { 42 | timeval now; 43 | gettimeofday(&now, &tzp); 44 | return ((double) now.tv_sec) + ((double) now.tv_usec)/1000000.; 45 | } 46 | void start () { 47 | on = 1; 48 | lastTime = getTime(); 49 | } 50 | double stop () { 51 | on = 0; 52 | double d = (getTime()-lastTime); 53 | totalTime += d; 54 | return d; 55 | } 56 | double stop (double weight) { 57 | on = 0; 58 | totalWeight += weight; 59 | double d = (getTime()-lastTime); 60 | totalTime += weight*d; 61 | return d; 62 | } 63 | 64 | double total() { 65 | if (on) return totalTime + getTime() - lastTime; 66 | else return totalTime; 67 | } 68 | 69 | double next() { 70 | if (!on) return 0.0; 71 | double t = getTime(); 72 | double td = t - lastTime; 73 | totalTime += td; 74 | lastTime = t; 75 | return td; 76 | } 77 | 78 | void reportT(double time) { 79 | std::cout << std::setprecision(3) << time << std::endl;; 80 | } 81 | 82 | void reportTime(double time) { 83 | reportT(time); 84 | } 85 | 86 | void reportStop(double weight, std::string str) { 87 | std::cout << str << " :" << weight << ": "; 88 | reportTime(stop(weight)); 89 | } 90 | 91 | void reportTotal() { 92 | double to = (totalWeight > 0.0) ? total()/totalWeight : total(); 93 | reportTime(to); 94 | totalTime = 0.0; 95 | totalWeight = 0.0; 96 | } 97 | 98 | void reportTotal(std::string str) { 99 | std::cout << str << " : "; 100 | reportTotal();} 101 | 102 | void reportNext() {reportTime(next());} 103 | 104 | void reportNext(std::string str) {std::cout << str << " : "; reportNext();} 105 | }; 106 | 107 | static timer _tm; 108 | #define timeStatement(_A,_string) _tm.start(); _A; _tm.reportNext(_string); 109 | #define startTime() _tm.start(); 110 | #define stopTime(_weight,_str) _tm.reportStop(_weight,_str); 111 | #define reportTime(_str) _tm.reportTotal(_str); 112 | #define nextTime(_string) _tm.reportNext(_string); 113 | #define nextTimeN() _tm.reportT(_tm.next()); 114 | 115 | #endif // _BENCH_GETTIME_INCLUDED 116 | 117 | -------------------------------------------------------------------------------- /ligra/graph.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAPH_H 2 | #define GRAPH_H 3 | #include 4 | #include 5 | #include 6 | #include "vertex.h" 7 | #include "compressedVertex.h" 8 | #include "parallel.h" 9 | using namespace std; 10 | 11 | // ************************************************************** 12 | // ADJACENCY ARRAY REPRESENTATION 13 | // ************************************************************** 14 | 15 | // Class that handles implementation specific freeing of memory 16 | // owned by the graph 17 | struct Deletable { 18 | public: 19 | virtual void del() = 0; 20 | }; 21 | 22 | template 23 | struct Uncompressed_Mem : public Deletable { 24 | public: 25 | vertex* V; 26 | long n; 27 | long m; 28 | void* allocatedInplace, * inEdges; 29 | 30 | Uncompressed_Mem(vertex* VV, long nn, long mm, void* ai, void* _inEdges = NULL) 31 | : V(VV), n(nn), m(mm), allocatedInplace(ai), inEdges(_inEdges) { } 32 | 33 | void del() { 34 | if (allocatedInplace == NULL) 35 | for (long i=0; i < n; i++) V[i].del(); 36 | else free(allocatedInplace); 37 | free(V); 38 | if(inEdges != NULL) free(inEdges); 39 | } 40 | }; 41 | 42 | template 43 | struct Uncompressed_Memhypergraph : public Deletable { 44 | public: 45 | vertex* V; 46 | vertex* H; 47 | long nv; 48 | long mv; 49 | long nh; 50 | long mh; 51 | void* edgesV, *inEdgesV, *edgesH, *inEdgesH; 52 | 53 | Uncompressed_Memhypergraph(vertex* VV, vertex* HH, long nnv, long mmv, long nnh, long mmh, void* _edgesV, void* _edgesH, void* _inEdgesV = NULL, void* _inEdgesH = NULL) 54 | : V(VV), H(HH), nv(nnv), mv(mmv), nh(nnh), mh(mmh), edgesV(_edgesV), edgesH(_edgesH), inEdgesV(_inEdgesV), inEdgesH(_inEdgesH) { } 55 | 56 | void del() { 57 | free(edgesV); 58 | free(edgesH); 59 | free(V); 60 | free(H); 61 | if(inEdgesV != NULL) free(inEdgesV); 62 | if(inEdgesH != NULL) free(inEdgesH); 63 | } 64 | }; 65 | 66 | template 67 | struct Compressed_Mem : public Deletable { 68 | public: 69 | vertex* V; 70 | char* s; 71 | 72 | Compressed_Mem(vertex* _V, char* _s) : 73 | V(_V), s(_s) { } 74 | 75 | void del() { 76 | free(V); 77 | free(s); 78 | } 79 | }; 80 | 81 | template 82 | struct Compressed_Memhypergraph : public Deletable { 83 | public: 84 | vertex* V; 85 | vertex* H; 86 | char* s; 87 | 88 | Compressed_Memhypergraph(vertex* _V, vertex* _H, char* _s) : 89 | V(_V), H(_H), s(_s) { } 90 | 91 | void del() { 92 | free(V); 93 | free(H); 94 | free(s); 95 | } 96 | }; 97 | 98 | template 99 | struct graph { 100 | vertex *V; 101 | long n; 102 | long m; 103 | bool transposed; 104 | uintE* flags; 105 | Deletable *D; 106 | 107 | graph(vertex* _V, long _n, long _m, Deletable* _D) : V(_V), n(_n), m(_m), 108 | D(_D), flags(NULL), transposed(0) {} 109 | 110 | graph(vertex* _V, long _n, long _m, Deletable* _D, uintE* _flags) : V(_V), 111 | n(_n), m(_m), D(_D), flags(_flags), transposed(0) {} 112 | 113 | void del() { 114 | if (flags != NULL) free(flags); 115 | D->del(); 116 | free(D); 117 | } 118 | 119 | void transpose() { 120 | if ((sizeof(vertex) == sizeof(asymmetricVertex)) || 121 | (sizeof(vertex) == sizeof(compressedAsymmetricVertex))) { 122 | parallel_for(long i=0;i 131 | struct hypergraph { 132 | vertex *V; 133 | vertex *H; 134 | long nv; 135 | long mv; 136 | long nh; 137 | long mh; 138 | bool transposed; 139 | uintE* flags; 140 | Deletable *D; 141 | 142 | hypergraph(vertex* _V, vertex* _H, long _nv, long _mv, long _nh, long _mh, Deletable* _D) : V(_V), H(_H), nv(_nv), mv(_mv), nh(_nh), mh(_mh), 143 | D(_D), flags(NULL), transposed(0) {} 144 | 145 | hypergraph(vertex* _V, vertex* _H, long _nv, long _mv, long _nh, long _mh, Deletable* _D, uintE* _flags) : V(_V), H(_H), 146 | nv(_nv), mv(_mv), nh(_nh), mh(_mh), D(_D), flags(_flags), transposed(0) {} 147 | 148 | void del() { 149 | if (flags != NULL) free(flags); 150 | D->del(); 151 | free(D); 152 | } 153 | void initFlags() { 154 | flags = newA(uintE,max(nv,nh)); 155 | parallel_for(long i=0;i 4 | 5 | using namespace std; 6 | 7 | template 8 | struct Maybe { 9 | // pays an extra byte for NONE/SOME 10 | // avoid Maybe*---this is basically free otherwise 11 | bool exists; 12 | T t; 13 | Maybe(const T& _t) : t(_t), exists(true) {} 14 | Maybe() : exists(false) {} 15 | }; 16 | 17 | inline const Maybe > wrap(const uintE& l, const uintE& r) { 18 | auto t = Maybe >(make_tuple(l, r)); 19 | t.exists = (l != UINT_E_MAX) && (r != UINT_E_MAX); 20 | return t; 21 | } 22 | 23 | template 24 | inline const Maybe > wrap(const L& l, const Maybe& r) { 25 | auto t = Maybe >(make_tuple(l, getT(r))); 26 | t.exists = r.exists; 27 | return t; 28 | } 29 | 30 | template 31 | inline Maybe > wrap(const Maybe& l, const R& r) { 32 | auto t = Maybe >(make_tuple(getT(l), r)); 33 | t.exists = l.exists; 34 | return t; 35 | } 36 | 37 | template 38 | inline Maybe > wrap(const Maybe& l, const Maybe& r) { 39 | auto t = Maybe >(make_tuple(getT(l), getT(r))); 40 | t.exists = l.exists && r.exists; 41 | return t; 42 | } 43 | 44 | template 45 | inline bool isSome(const Maybe& m) { 46 | return m.exists; 47 | } 48 | 49 | template 50 | inline T getT(const Maybe& m) { 51 | return m.t; 52 | } 53 | -------------------------------------------------------------------------------- /ligra/parallel.h: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | #ifndef _PARALLEL_H 25 | #define _PARALLEL_H 26 | 27 | #if defined(CILK) 28 | #include 29 | #define parallel_main main 30 | #define parallel_for cilk_for 31 | #define parallel_for_1 _Pragma("cilk_grainsize = 1") cilk_for 32 | #define parallel_for_256 _Pragma("cilk_grainsize = 256") cilk_for 33 | #include 34 | #include 35 | #include 36 | #include 37 | static int getWorkers() { 38 | return __cilkrts_get_nworkers(); 39 | } 40 | static void setWorkers(int n) { 41 | __cilkrts_end_cilk(); 42 | //__cilkrts_init(); 43 | std::stringstream ss; ss << n; 44 | if (0 != __cilkrts_set_param("nworkers", ss.str().c_str())) { 45 | std::cerr << "failed to set worker count!" << std::endl; 46 | std::abort(); 47 | } 48 | } 49 | 50 | // intel cilk+ 51 | #elif defined(CILKP) 52 | #include 53 | #define parallel_for cilk_for 54 | #define parallel_main main 55 | #define parallel_for_1 _Pragma("cilk grainsize = 1") cilk_for 56 | #define parallel_for_256 _Pragma("cilk grainsize = 256") cilk_for 57 | #include 58 | #include 59 | #include 60 | #include 61 | static int getWorkers() { 62 | return __cilkrts_get_nworkers(); 63 | } 64 | static void setWorkers(int n) { 65 | __cilkrts_end_cilk(); 66 | //__cilkrts_init(); 67 | std::stringstream ss; ss << n; 68 | if (0 != __cilkrts_set_param("nworkers", ss.str().c_str())) { 69 | std::cerr << "failed to set worker count!" << std::endl; 70 | std::abort(); 71 | } 72 | } 73 | 74 | // openmp 75 | #elif defined(OPENMP) 76 | #include 77 | #define cilk_spawn 78 | #define cilk_sync 79 | #define parallel_main main 80 | #define parallel_for _Pragma("omp parallel for") for 81 | #define parallel_for_1 _Pragma("omp parallel for schedule (static,1)") for 82 | #define parallel_for_256 _Pragma("omp parallel for schedule (static,256)") for 83 | static int getWorkers() { return omp_get_max_threads(); } 84 | static void setWorkers(int n) { omp_set_num_threads(n); } 85 | 86 | // c++ 87 | #else 88 | #define cilk_spawn 89 | #define cilk_sync 90 | #define parallel_main main 91 | #define parallel_for for 92 | #define parallel_for_1 for 93 | #define parallel_for_256 for 94 | #define cilk_for for 95 | static int getWorkers() { return 1; } 96 | static void setWorkers(int n) { } 97 | 98 | #endif 99 | 100 | #include 101 | 102 | #if defined(LONG) 103 | typedef long intT; 104 | typedef unsigned long uintT; 105 | #define INT_T_MAX LONG_MAX 106 | #define UINT_T_MAX ULONG_MAX 107 | #else 108 | typedef int intT; 109 | typedef unsigned int uintT; 110 | #define INT_T_MAX INT_MAX 111 | #define UINT_T_MAX UINT_MAX 112 | #endif 113 | 114 | //edges store 32-bit quantities unless EDGELONG is defined 115 | #if defined(EDGELONG) 116 | typedef long intE; 117 | typedef unsigned long uintE; 118 | #define INT_E_MAX LONG_MAX 119 | #define UINT_E_MAX ULONG_MAX 120 | #else 121 | typedef int intE; 122 | typedef unsigned int uintE; 123 | #define INT_E_MAX INT_MAX 124 | #define UINT_E_MAX UINT_MAX 125 | #endif 126 | 127 | #endif // _PARALLEL_H 128 | -------------------------------------------------------------------------------- /ligra/parseCommandLine.h: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2011 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #ifndef _PARSE_COMMAND_LINE 24 | #define _PARSE_COMMAND_LINE 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | using namespace std; 32 | 33 | struct commandLine { 34 | int argc; 35 | char** argv; 36 | string comLine; 37 | commandLine(int _c, char** _v, string _cl) 38 | : argc(_c), argv(_v), comLine(_cl) {} 39 | 40 | commandLine(int _c, char** _v) 41 | : argc(_c), argv(_v), comLine("bad arguments") {} 42 | 43 | void badArgument() { 44 | cout << "usage: " << argv[0] << " " << comLine << endl; 45 | abort(); 46 | } 47 | 48 | // get an argument 49 | // i is indexed from the last argument = 0, second to last indexed 1, .. 50 | char* getArgument(int i) { 51 | if (argc < 2+i) badArgument(); 52 | return argv[argc-1-i]; 53 | } 54 | 55 | // looks for two filenames 56 | pair IOFileNames() { 57 | if (argc < 3) badArgument(); 58 | return pair(argv[argc-2],argv[argc-1]); 59 | } 60 | 61 | pair sizeAndFileName() { 62 | if (argc < 3) badArgument(); 63 | return pair(atoi(argv[argc-2]),(char*) argv[argc-1]); 64 | } 65 | 66 | bool getOption(string option) { 67 | for (int i = 1; i < argc; i++) 68 | if ((string) argv[i] == option) return true; 69 | return false; 70 | } 71 | 72 | char* getOptionValue(string option) { 73 | for (int i = 1; i < argc-1; i++) 74 | if ((string) argv[i] == option) return argv[i+1]; 75 | return NULL; 76 | } 77 | 78 | string getOptionValue(string option, string defaultValue) { 79 | for (int i = 1; i < argc-1; i++) 80 | if ((string) argv[i] == option) return (string) argv[i+1]; 81 | return defaultValue; 82 | } 83 | 84 | int getOptionIntValue(string option, int defaultValue) { 85 | for (int i = 1; i < argc-1; i++) 86 | if ((string) argv[i] == option) { 87 | int r = atoi(argv[i+1]); 88 | return r; 89 | } 90 | return defaultValue; 91 | } 92 | 93 | long getOptionLongValue(string option, long defaultValue) { 94 | for (int i = 1; i < argc-1; i++) 95 | if ((string) argv[i] == option) { 96 | long r = atol(argv[i+1]); 97 | return r; 98 | } 99 | return defaultValue; 100 | } 101 | 102 | double getOptionDoubleValue(string option, double defaultValue) { 103 | for (int i = 1; i < argc-1; i++) 104 | if ((string) argv[i] == option) { 105 | double val; 106 | if (sscanf(argv[i+1], "%lf", &val) == EOF) { 107 | badArgument(); 108 | } 109 | return val; 110 | } 111 | return defaultValue; 112 | } 113 | 114 | }; 115 | 116 | #endif // _PARSE_COMMAND_LINE 117 | -------------------------------------------------------------------------------- /ligra/quickSort.h: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2013 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #ifndef A_QSORT_INCLUDED 24 | #define A_QSORT_INCLUDED 25 | #include 26 | #include "parallel.h" 27 | 28 | template 29 | void insertionSort(E* A, intT n, BinPred f) { 30 | for (intT i=0; i < n; i++) { 31 | E v = A[i]; 32 | E* B = A + i; 33 | while (--B >= A && f(v,*B)) *(B+1) = *B; 34 | *(B+1) = v; 35 | } 36 | } 37 | 38 | #define ISORT 25 39 | 40 | template 41 | E median(E a, E b, E c, BinPred f) { 42 | return f(a,b) ? (f(b,c) ? b : (f(a,c) ? c : a)) 43 | : (f(a,c) ? a : (f(b,c) ? c : b)); 44 | } 45 | 46 | // Quicksort based on median of three elements as pivot 47 | // and uses insertionSort for small inputs 48 | template 49 | void quickSort(E* A, intT n, BinPred f) { 50 | if (n < ISORT) insertionSort(A, n, f); 51 | else { 52 | //E p = std::__median(A[n/4],A[n/2],A[(3*n)/4],f); 53 | E p = median(A[n/4],A[n/2],A[(3*n)/4],f); 54 | E* L = A; // below L are less than pivot 55 | E* M = A; // between L and M are equal to pivot 56 | E* R = A+n-1; // above R are greater than pivot 57 | while (1) { 58 | while (!f(p,*M)) { 59 | if (f(*M,p)) std::swap(*M,*(L++)); 60 | if (M >= R) break; 61 | M++; 62 | } 63 | while (f(p,*R)) R--; 64 | if (M >= R) break; 65 | std::swap(*M,*R--); 66 | if (f(*M,p)) std::swap(*M,*(L++)); 67 | M++; 68 | } 69 | cilk_spawn quickSort(A, L-A, f); 70 | quickSort(M, A+n-M, f); // Exclude all elts that equal pivot 71 | cilk_sync; 72 | } 73 | } 74 | 75 | #endif // _A_QSORT_INCLUDED 76 | -------------------------------------------------------------------------------- /ligra/sequentialHT.h: -------------------------------------------------------------------------------- 1 | // This code is based on the paper "Phase-Concurrent Hash Tables for 2 | // Determinism" by Julian Shun and Guy Blelloch from SPAA 2014. 3 | // Copyright (c) 2014 Julian Shun and Guy Blelloch 4 | // 5 | // Permission is hereby granted, free of charge, to any person 6 | // obtaining a copy of this software and associated documentation 7 | // files (the "Software"), to deal in the Software without 8 | // restriction, including without limitation the rights (to use, copy, 9 | // modify, merge, publish, distribute, sublicense, and/or sell copies 10 | // of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be 14 | // included in all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | // MERCHANBILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | #pragma once 25 | 26 | #include "parallel.h" 27 | #include "utils.h" 28 | #include "maybe.h" 29 | using namespace std; 30 | 31 | template 32 | class sequentialHT { 33 | typedef tuple T; 34 | 35 | public: 36 | size_t m; 37 | intT mask; 38 | T empty; 39 | K max_key; 40 | T* table; 41 | 42 | inline size_t toRange(size_t h) {return h & mask;} 43 | inline size_t firstIndex(K v) {return toRange(pbbs::hash64(v));} 44 | inline size_t incrementIndex(size_t h) {return toRange(h+1);} 45 | 46 | sequentialHT(T* _table, size_t size, float loadFactor, tuple _empty) : 47 | m((size_t) 1 << pbbs::log2_up((size_t)(loadFactor*size))), 48 | mask(m-1), table(_table), empty(_empty) { max_key = get<0>(empty); } 49 | 50 | // m must be a power of two 51 | sequentialHT(T* _table, size_t _m, tuple _empty) : 52 | m((size_t)_m), mask(m-1), table(_table), empty(_empty) { max_key = get<0>(empty); } 53 | 54 | template 55 | inline void insertF(tuple& v, F& f) { 56 | K vKey = get<0>(v); 57 | size_t h = firstIndex(vKey); 58 | while (1) { 59 | auto k = get<0>(table[h]); 60 | if (k == max_key) { 61 | get<0>(table[h]) = vKey; 62 | V cur = get<1>(table[h]); 63 | get<1>(table[h]) = f(cur, v); 64 | return; 65 | } else if (k == vKey) { 66 | V cur = get<1>(table[h]); 67 | get<1>(table[h]) = f(cur, v); 68 | return; 69 | } 70 | h = incrementIndex(h); 71 | } 72 | } 73 | 74 | // V must support ++ 75 | inline void insertAdd(K& vKey) { 76 | size_t h = firstIndex(vKey); 77 | while (1) { 78 | auto k = get<0>(table[h]); 79 | if (k == max_key) { 80 | table[h] = make_tuple(vKey, 1); 81 | return; 82 | } else if (k == vKey) { 83 | get<1>(table[h])++; 84 | return; 85 | } 86 | h = incrementIndex(h); 87 | } 88 | } 89 | 90 | // V must support ++, T<1> must be numeric 91 | inline void insertAdd(T& v) { 92 | const K& vKey = get<0>(v); 93 | size_t h = firstIndex(vKey); 94 | while (1) { 95 | auto k = get<0>(table[h]); 96 | if (k == max_key) { 97 | table[h] = make_tuple(vKey, 1); 98 | return; 99 | } else if (k == vKey) { 100 | get<1>(table[h]) += get<1>(v); 101 | return; 102 | } 103 | h = incrementIndex(h); 104 | } 105 | } 106 | 107 | inline T find(K& v) { 108 | size_t h = firstIndex(v); 109 | T c = table[h]; 110 | while (1) { 111 | if (get<0>(c) == max_key) { 112 | return empty; 113 | } else if (get<0>(c) == v) { 114 | return c; 115 | } 116 | h = incrementIndex(h); 117 | c = table[h]; 118 | } 119 | } 120 | 121 | // F : KV -> E 122 | template 123 | inline size_t compactInto(F& f, E* Out) { 124 | size_t k = 0; 125 | for (size_t i=0; i < m; i++) { 126 | auto kv = table[i]; auto key = get<0>(kv); 127 | if (key != max_key) { 128 | table[i] = empty; 129 | Maybe value = f(kv); 130 | if (isSome(value)) { 131 | Out[k++] = getT(value); 132 | } 133 | } 134 | } 135 | return k; 136 | } 137 | 138 | }; 139 | 140 | -------------------------------------------------------------------------------- /ligra/transpose.h: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2010 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #ifndef A_TRANSPOSE_INCLUDED 24 | #define A_TRANSPOSE_INCLUDED 25 | 26 | #include "parallel.h" 27 | 28 | #define _TRANS_THRESHHOLD 64 29 | 30 | template 31 | struct transpose { 32 | E *A, *B; 33 | transpose(E *AA, E *BB) : A(AA), B(BB) {} 34 | 35 | void transR(intT rStart, intT rCount, intT rLength, 36 | intT cStart, intT cCount, intT cLength) { 37 | //cout << "cc,rc: " << cCount << "," << rCount << endl; 38 | if (cCount < _TRANS_THRESHHOLD && rCount < _TRANS_THRESHHOLD) { 39 | for (intT i=rStart; i < rStart + rCount; i++) 40 | for (intT j=cStart; j < cStart + cCount; j++) 41 | B[j*cLength + i] = A[i*rLength + j]; 42 | } else if (cCount > rCount) { 43 | intT l1 = cCount/2; 44 | intT l2 = cCount - cCount/2; 45 | cilk_spawn this->transR(rStart,rCount,rLength,cStart,l1,cLength); 46 | transR(rStart,rCount,rLength,cStart + l1,l2,cLength); 47 | cilk_sync; 48 | } else { 49 | intT l1 = rCount/2; 50 | intT l2 = rCount - rCount/2; 51 | cilk_spawn this->transR(rStart,l1,rLength,cStart,cCount,cLength); 52 | transR(rStart + l1,l2,rLength,cStart,cCount,cLength); 53 | cilk_sync; 54 | } 55 | } 56 | 57 | void trans(intT rCount, intT cCount) { 58 | transR(0,rCount,cCount,0,cCount,rCount); 59 | } 60 | }; 61 | 62 | template 63 | struct blockTrans { 64 | E *A, *B; 65 | intT *OA, *OB, *L; 66 | 67 | blockTrans(E *AA, E *BB, intT *OOA, intT *OOB, intT *LL) 68 | : A(AA), B(BB), OA(OOA), OB(OOB), L(LL) {} 69 | 70 | void transR(intT rStart, intT rCount, intT rLength, 71 | intT cStart, intT cCount, intT cLength) { 72 | //cout << "cc,rc: " << cCount << "," << rCount << endl; 73 | if (cCount < _TRANS_THRESHHOLD && rCount < _TRANS_THRESHHOLD) { 74 | for (intT i=rStart; i < rStart + rCount; i++) 75 | for (intT j=cStart; j < cStart + cCount; j++) { 76 | E* pa = A+OA[i*rLength + j]; 77 | E* pb = B+OB[j*cLength + i]; 78 | intT l = L[i*rLength + j]; 79 | //cout << "pa,pb,l: " << pa << "," << pb << "," << l << endl; 80 | for (intT k=0; k < l; k++) *(pb++) = *(pa++); 81 | } 82 | } else if (cCount > rCount) { 83 | intT l1 = cCount/2; 84 | intT l2 = cCount - cCount/2; 85 | cilk_spawn this->transR(rStart,rCount,rLength,cStart,l1,cLength); 86 | transR(rStart,rCount,rLength,cStart + l1,l2,cLength); 87 | cilk_sync; 88 | } else { 89 | intT l1 = rCount/2; 90 | intT l2 = rCount - rCount/2; 91 | cilk_spawn this->transR(rStart,l1,rLength,cStart,cCount,cLength); 92 | transR(rStart + l1,l2,rLength,cStart,cCount,cLength); 93 | cilk_sync; 94 | } 95 | } 96 | 97 | void trans(intT rCount, intT cCount) { 98 | transR(0,rCount,cCount,0,cCount,rCount); 99 | } 100 | 101 | } ; 102 | 103 | #endif // A_TRANSPOSE_INCLUDED 104 | -------------------------------------------------------------------------------- /tutorial/BFS.C: -------------------------------------------------------------------------------- 1 | #include "ligra.h" 2 | 3 | struct BFS_F { 4 | long* Parents; 5 | BFS_F(long* _Parents) : Parents(_Parents) {} 6 | inline bool updateAtomic (long s, long d){ //atomic version of Update 7 | //FILL IN 8 | } 9 | inline bool update (long s, long d) { //Update 10 | return updateAtomic(s,d); 11 | } 12 | inline bool cond (long d) { 13 | //FILL IN 14 | } 15 | }; 16 | 17 | template 18 | void Compute(graph& GA, commandLine P) { 19 | long start = P.getOptionLongValue("-r",0); 20 | long n = GA.n; 21 | //creates Parents array, initialized to all -1, except for start 22 | long* Parents = new long[n]; 23 | parallel_for(long i=0;i 20 | void Compute(graph& GA, commandLine P) { 21 | long start = P.getOptionLongValue("-r",0); 22 | long n = GA.n; 23 | //initialize ShortestPathLen to "infinity" 24 | long* ShortestPathLen = new long[n]; 25 | {parallel_for(long i=0;i 18 | void Compute(graph& GA, commandLine P) { 19 | long n = GA.n; 20 | long* IDs = new long[n]; 21 | {parallel_for(long i=0;i 18 | struct Deg_LessThan_K { 19 | vertex* V; 20 | long* coreNumbers; 21 | long* Degrees; 22 | long k; 23 | Deg_LessThan_K(vertex* _V, long* _Degrees, long* _coreNumbers, long _k) : 24 | V(_V), k(_k), Degrees(_Degrees), coreNumbers(_coreNumbers) {} 25 | inline bool operator () (long i) { 26 | //FILL IN 27 | } 28 | }; 29 | 30 | template 31 | struct Deg_AtLeast_K { 32 | vertex* V; 33 | long *Degrees; 34 | long k; 35 | Deg_AtLeast_K(vertex* _V, long* _Degrees, long _k) : 36 | V(_V), k(_k), Degrees(_Degrees) {} 37 | inline bool operator () (long i) { 38 | // FILL IN 39 | } 40 | }; 41 | 42 | //assumes symmetric graph 43 | // 1) iterate over all remaining active vertices 44 | // 2) for each active vertex, remove if induced degree < k. Any vertex removed has 45 | // core-number (k-1) (part of (k-1)-core, but not k-core) 46 | // 3) stop once no vertices are removed. Vertices remaining are in the k-core. 47 | template 48 | void Compute(graph& GA, commandLine P) { 49 | const long n = GA.n; 50 | bool* active = newA(bool,n); 51 | {parallel_for(long i=0;i(GA.V,Degrees,coreNumbers,k)); 64 | vertexSubset remaining = vertexFilter(Frontier,Deg_AtLeast_K(GA.V,Degrees,k)); 65 | Frontier.del(); 66 | Frontier = remaining; 67 | if (0 == toRemove.numNonzeros()) { // fixed point. found k-core 68 | toRemove.del(); 69 | break; 70 | } 71 | else { 72 | vertexSubset output = edgeMap(GA,toRemove,Update_Deg(Degrees)); 73 | toRemove.del(); output.del(); 74 | } 75 | } 76 | if(Frontier.numNonzeros() == 0) { largestCore = k-1; break; } 77 | } 78 | cout << "largestCore was " << largestCore << endl; 79 | Frontier.del(); free(coreNumbers); free(Degrees); 80 | } 81 | -------------------------------------------------------------------------------- /tutorial/Makefile: -------------------------------------------------------------------------------- 1 | ifdef LONG 2 | INTT = -DLONG 3 | endif 4 | 5 | ifdef EDGELONG 6 | INTE = -DEDGELONG 7 | endif 8 | 9 | #compilers 10 | ifdef CILK 11 | PCC = g++ 12 | PCFLAGS = -fcilkplus -lcilkrts -O3 -DCILK $(INTT) $(INTE) 13 | PLFLAGS = -fcilkplus -lcilkrts 14 | 15 | else ifdef MKLROOT 16 | PCC = icpc 17 | PCFLAGS = -O3 -DCILKP $(INTT) $(INTE) 18 | 19 | else ifdef OPENMP 20 | PCC = g++ 21 | PCFLAGS = -fopenmp -march=native -O3 -DOPENMP $(INTT) $(INTE) 22 | 23 | else 24 | PCC = g++ 25 | PCFLAGS = -O3 $(INTT) $(INTE) 26 | endif 27 | 28 | COMMON= ligra.h graph.h compressedVertex.h vertex.h utils.h IO.h parallel.h gettime.h quickSort.h parseCommandLine.h byte.h byteRLE.h nibble.h byte-pd.h byteRLE-pd.h nibble-pd.h vertexSubset.h encoder.C blockRadixSort.h transpose.h index_map.h maybe.h sequence.h edgeMap_utils.h binary_search.h 29 | 30 | ALL= encoder BFS BellmanFord Components Radii KCore 31 | 32 | all: $(ALL) 33 | 34 | % : %.C $(COMMON) 35 | $(PCC) $(PCFLAGS) -o $@ $< 36 | 37 | $(COMMON): 38 | ln -s ../ligra/$@ . 39 | 40 | .PHONY : clean 41 | 42 | clean : 43 | rm -f *.o $(ALL) 44 | 45 | cleansrc : 46 | rm -f *.o $(ALL) 47 | rm $(COMMON) 48 | -------------------------------------------------------------------------------- /tutorial/Radii.C: -------------------------------------------------------------------------------- 1 | #include "ligra.h" 2 | 3 | //atomically do bitwise-OR of *a with b and store in location a 4 | template 5 | inline void writeOr(ET *a, ET b) { 6 | volatile ET newV, oldV; 7 | do {oldV = *a; newV = oldV | b;} 8 | while ((oldV != newV) && !CAS(a, oldV, newV)); 9 | } 10 | 11 | struct Radii_F { 12 | long round; 13 | long* radii; 14 | long* Visited, *NextVisited; 15 | Radii_F(long* _Visited, long* _NextVisited, long* _radii, long _round) : 16 | Visited(_Visited), NextVisited(_NextVisited), radii(_radii), round(_round) 17 | {} 18 | inline bool updateAtomic (long s, long d){ //atomic Update 19 | //FILL IN 20 | } 21 | inline bool update (long s, long d){ 22 | return updateAtomic(s,d); 23 | } 24 | inline bool cond (long d) { 25 | //FILL IN 26 | } 27 | }; 28 | 29 | //function passed to vertex map to sync NextVisited and Visited 30 | struct Radii_Vertex_F { 31 | long* Visited, *NextVisited; 32 | Radii_Vertex_F(long* _Visited, long* _NextVisited) : 33 | Visited(_Visited), NextVisited(_NextVisited) {} 34 | inline bool operator() (long i) { 35 | Visited[i] = NextVisited[i]; 36 | return 1; 37 | } 38 | }; 39 | 40 | template 41 | void Compute(graph& GA, commandLine P) { 42 | long n = GA.n; 43 | long* radii = new long[n]; 44 | long* Visited = new long[n]; 45 | long* NextVisited = new long[n]; 46 | {parallel_for(long i=0;i "); 32 | char* iFile = P.getArgument(1); 33 | char* oFile = P.getArgument(0); 34 | bool wgh = P.getOption("-w"); 35 | if(!wgh) { 36 | hyperedgeArray G = readKONECT(iFile); 37 | writeHypergraphToFile(hypergraphFromHyperedges(G),oFile); 38 | } else { 39 | wghHyperedgeArray G = readWghKONECT(iFile); 40 | writeWghHypergraphToFile(wghHypergraphFromWghHyperedges(G),oFile); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /utils/KONECTtoMESH.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | #include "parseCommandLine.h" 26 | #include "graphIO.h" 27 | #include "parallel.h" 28 | 29 | template 30 | void xToCSVString(char* s, edge a) { 31 | int l = xToStringLen(a.u); 32 | xToString(s, a.u); 33 | s[l] = ','; 34 | xToString(s+l+1, a.v); 35 | } 36 | 37 | template 38 | _seq arrayToCSVString(edge* A, long n) { 39 | long* L = newA(long,n); 40 | {parallel_for(long i=0; i < n; i++) L[i] = xToStringLen(A[i])+1;} 41 | long m = sequence::scan(L,L,n,addF(),(long) 0); 42 | char* B = newA(char,m); 43 | parallel_for(long j=0; j < m; j++) 44 | B[j] = 0; 45 | parallel_for(long i=0; i < n-1; i++) { 46 | xToCSVString(B + L[i],A[i]); 47 | B[L[i+1] - 1] = '\n'; 48 | } 49 | xToCSVString(B + L[n-1],A[n-1]); 50 | B[m-1] = '\n'; 51 | free(L); 52 | char* C = newA(char,m+1); 53 | long mm = sequence::filter(B,C,m,notZero()); 54 | C[mm] = 0; 55 | free(B); 56 | return _seq(C,mm); 57 | } 58 | 59 | int parallel_main(int argc, char* argv[]) { 60 | commandLine P(argc,argv," "); 61 | char* iFile = P.getArgument(1); 62 | char* oFile = P.getArgument(0); 63 | hyperedgeArray G = readKONECT(iFile); 64 | ofstream file (oFile, ios::out | ios::binary); 65 | long BSIZE = 1000000; 66 | long offset = 0; 67 | while (offset < G.mh) { 68 | // Generates a string for a sequence of size at most BSIZE 69 | // and then wrties it to the output stream 70 | _seq S = arrayToCSVString(G.HE+offset,min(BSIZE,G.mh-offset)); 71 | file.write(S.A, S.n); 72 | S.del(); 73 | offset += BSIZE; 74 | } 75 | 76 | //writeArrayToStream< edge >(file,G.VE,G.mv); 77 | file.close(); 78 | } 79 | -------------------------------------------------------------------------------- /utils/Makefile: -------------------------------------------------------------------------------- 1 | ifdef LONG 2 | INTT = -DLONG 3 | endif 4 | 5 | ifdef EDGELONG 6 | INTE = -DEDGELONG 7 | endif 8 | 9 | #compilers 10 | ifdef CILK 11 | PCC = g++ 12 | PCFLAGS = -std=c++14 -fcilkplus -lcilkrts -O3 -DCILK $(INTT) $(INTE) 13 | PLFLAGS = -fcilkplus -lcilkrts 14 | 15 | else ifdef MKLROOT 16 | PCC = icpc 17 | PCFLAGS = -std=c++14 -O3 -DCILKP $(INTT) $(INTE) 18 | 19 | else ifdef OPENMP 20 | PCC = g++ 21 | PCFLAGS = -std=c++14 -fopenmp -march=native -O3 -DOPENMP $(INTT) $(INTE) 22 | 23 | else 24 | PCC = g++ 25 | PCFLAGS = -std=c++14 -O3 $(INTT) $(INTE) 26 | endif 27 | 28 | COMMON = utils.h parseCommandLine.h parallel.h quickSort.h blockRadixSort.h transpose.h 29 | LOCAL_COMMON = graphIO.h 30 | GENERATORS = rMatGraph gridGraph randLocalGraph SNAPtoAdj wghSNAPtoAdj adjGraphAddWeights adjToBinary communityToHyperAdj hyperAdjToBinary adjHypergraphAddWeights randHypergraph KONECTtoHyperAdj KONECTtoClique communityToClique communityToMESH KONECTtoMESH 31 | 32 | .PHONY: all clean 33 | all: $(GENERATORS) 34 | 35 | $(COMMON): 36 | ln -s ../ligra/$@ . 37 | 38 | % : %.C $(COMMON) $(LOCAL_COMMON) 39 | $(PCC) $(PCFLAGS) -o $@ $< 40 | 41 | clean : 42 | rm -f *.o $(GENERATORS) 43 | 44 | cleansrc : 45 | make -s clean 46 | rm -f $(COMMON) 47 | -------------------------------------------------------------------------------- /utils/SNAPtoAdj.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | //Converts a SNAP graph (http://snap.stanford.edu/data/index.html) to 26 | //Ligra adjacency graph format. To symmetrize the graph, pass the "-s" 27 | //flag. For undirected graphs on SNAP, the "-s" flag must be passed 28 | //since each edge appears in only one direction 29 | 30 | #include "parseCommandLine.h" 31 | #include "graphIO.h" 32 | #include "parallel.h" 33 | 34 | int parallel_main(int argc, char* argv[]) { 35 | commandLine P(argc,argv,"[-s] "); 36 | char* iFile = P.getArgument(1); 37 | char* oFile = P.getArgument(0); 38 | bool sym = P.getOption("-s"); 39 | edgeArray G = readSNAP(iFile); 40 | writeGraphToFile(graphFromEdges(G,sym),oFile); 41 | } 42 | -------------------------------------------------------------------------------- /utils/adjGraphAddWeights.C: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2011 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | // Adds a random integer weight in [1...log(n)] to each edge 24 | #include 25 | #include "graphIO.h" 26 | #include "parseCommandLine.h" 27 | #include "parallel.h" 28 | using namespace benchIO; 29 | using namespace std; 30 | 31 | int parallel_main(int argc, char* argv[]) { 32 | commandLine P(argc,argv," "); 33 | pair fnames = P.IOFileNames(); 34 | char* iFile = fnames.first; 35 | char* oFile = fnames.second; 36 | 37 | graph G = readGraphFromFile(iFile); 38 | 39 | long m = G.m; 40 | long n = G.n; 41 | 42 | intT* Weights = newA(intT,m); 43 | 44 | intT maxEdgeLen = log2(n); 45 | intT* Choices = newA(intT,2*maxEdgeLen); 46 | 47 | parallel_for (intT i=0;i* WV = newA(wghVertex,n); 60 | intT* Neighbors_start = G.allocatedInplace+2+n; 61 | 62 | parallel_for(long i=0;i i) { 74 | for(long k=0;k WG(WV,n,m,(intT*)G.allocatedInplace,Weights); 86 | int r = writeWghGraphToFile(WG,oFile); 87 | 88 | WG.del(); 89 | 90 | return r; 91 | } 92 | -------------------------------------------------------------------------------- /utils/adjHypergraphAddWeights.C: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2011 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | // Adds a random integer weight in [1...log(n)] to each hyperedge 24 | #include 25 | #include "graphIO.h" 26 | #include "parseCommandLine.h" 27 | #include "parallel.h" 28 | using namespace benchIO; 29 | using namespace std; 30 | 31 | int parallel_main(int argc, char* argv[]) { 32 | commandLine P(argc,argv," "); 33 | pair fnames = P.IOFileNames(); 34 | char* iFile = fnames.first; 35 | char* oFile = fnames.second; 36 | 37 | hypergraph G = readHypergraphFromFile(iFile); 38 | 39 | long nv = G.nv, mv = G.mv, nh = G.nh, mh = G.mh; 40 | 41 | intT* WeightsV = newA(intT,mv); 42 | intT* WeightsH = newA(intT,mh); 43 | intT* InWeights = newA(intT,nh); //each hyperedge has an incoming weight 44 | intT* OutWeights = newA(intT,nh); //each hyperedge has an outgoing weight 45 | intT maxEdgeLen = log2(max(nv,nh)); 46 | intT* Choices = newA(intT,maxEdgeLen); 47 | 48 | parallel_for (intT i=0;i* WV = newA(wghVertex,nv); 60 | wghVertex* WH = newA(wghVertex,nh); 61 | intT* Neighbors_startV = G.allocatedInplace+4+nv; 62 | intT* Neighbors_startH = G.allocatedInplace+4+nv+mv+nh; 63 | 64 | {parallel_for(long i=0;i WG(WV,WH,nv,mv,nh,mh,G.allocatedInplace); 83 | int r = writeWghHypergraphToFile(WG,oFile); 84 | 85 | WG.del(); 86 | 87 | return r; 88 | } 89 | -------------------------------------------------------------------------------- /utils/adjToBinary.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | // Converts a Ligra graph in adjacency graph format into binary format 26 | 27 | #include "parseCommandLine.h" 28 | #include "graphIO.h" 29 | #include "parallel.h" 30 | #include 31 | #include 32 | using namespace benchIO; 33 | using namespace std; 34 | 35 | int parallel_main(int argc, char* argv[]) { 36 | commandLine P(argc,argv," [-w] "); 37 | char* iFile = P.getArgument(3); 38 | char* idxFile = P.getArgument(2); 39 | char* adjFile = P.getArgument(1); 40 | char* configFile = P.getArgument(0); 41 | bool weighted = P.getOptionValue("-w"); 42 | 43 | ofstream idx(idxFile, ofstream::out | ios::binary); 44 | ofstream adj(adjFile, ofstream::out | ios::binary); 45 | ofstream config(configFile, ofstream::out); 46 | if(!weighted) { 47 | graph G = readGraphFromFile(iFile); 48 | config << G.n; 49 | uintT* In = G.allocatedInplace; 50 | uintT* offsets = In+2; 51 | uintT* edges = In+2+G.n; 52 | idx.write((char*)offsets,sizeof(uintT)*G.n); 53 | if(sizeof(uintE) != sizeof(uintT)) { 54 | uintE* E = newA(uintE,G.m); 55 | parallel_for(long i=0;i G = readWghGraphFromFile(iFile); 64 | config << G.n; 65 | uintT* In = G.allocatedInplace; 66 | uintT* offsets = In+2; 67 | uintT* edges = In+2+G.n; 68 | idx.write((char*)offsets,sizeof(uintT)*G.n); 69 | if(sizeof(uintE) != sizeof(uintT)) { 70 | intE* E = newA(intE,2*G.m); 71 | parallel_for(long i=0;i<2*G.m;i++) E[i] = edges[i]; 72 | adj.write((char*)E,sizeof(intE)*2*G.m); 73 | free(E); 74 | } else { 75 | adj.write((char*)edges,sizeof(uintT)*2*G.m); //edges and weights 76 | } 77 | G.del(); 78 | } 79 | config.close(); 80 | idx.close(); 81 | adj.close(); 82 | } 83 | -------------------------------------------------------------------------------- /utils/blockRadixSort.h: -------------------------------------------------------------------------------- 1 | ../ligra/blockRadixSort.h -------------------------------------------------------------------------------- /utils/communityToHyperAdj.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | #include "parseCommandLine.h" 26 | #include "graphIO.h" 27 | #include "parallel.h" 28 | 29 | //pass -w flag for weighted input 30 | int parallel_main(int argc, char* argv[]) { 31 | commandLine P(argc,argv,"[-w] "); 32 | char* iFile = P.getArgument(1); 33 | char* oFile = P.getArgument(0); 34 | bool wgh = P.getOption("-w"); 35 | if(!wgh) { 36 | hyperedgeArray G = readHyperedges(iFile); 37 | writeHypergraphToFile(hypergraphFromHyperedges(G),oFile); 38 | } else { 39 | wghHyperedgeArray G = readWghHyperedges(iFile); 40 | writeWghHypergraphToFile(wghHypergraphFromWghHyperedges(G),oFile); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /utils/communityToMESH.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | #include "parseCommandLine.h" 26 | #include "graphIO.h" 27 | #include "parallel.h" 28 | 29 | template 30 | void xToCSVString(char* s, edge a) { 31 | int l = xToStringLen(a.u); 32 | xToString(s, a.u); 33 | s[l] = ','; 34 | xToString(s+l+1, a.v); 35 | } 36 | 37 | template 38 | _seq arrayToCSVString(edge* A, long n) { 39 | long* L = newA(long,n); 40 | {parallel_for(long i=0; i < n; i++) L[i] = xToStringLen(A[i])+1;} 41 | long m = sequence::scan(L,L,n,addF(),(long) 0); 42 | char* B = newA(char,m); 43 | parallel_for(long j=0; j < m; j++) 44 | B[j] = 0; 45 | parallel_for(long i=0; i < n-1; i++) { 46 | xToCSVString(B + L[i],A[i]); 47 | B[L[i+1] - 1] = '\n'; 48 | } 49 | xToCSVString(B + L[n-1],A[n-1]); 50 | B[m-1] = '\n'; 51 | free(L); 52 | char* C = newA(char,m+1); 53 | long mm = sequence::filter(B,C,m,notZero()); 54 | C[mm] = 0; 55 | free(B); 56 | return _seq(C,mm); 57 | } 58 | 59 | int parallel_main(int argc, char* argv[]) { 60 | commandLine P(argc,argv," "); 61 | char* iFile = P.getArgument(1); 62 | char* oFile = P.getArgument(0); 63 | hyperedgeArray G = readHyperedges(iFile); 64 | ofstream file (oFile, ios::out | ios::binary); 65 | long BSIZE = 1000000; 66 | long offset = 0; 67 | while (offset < G.mh) { 68 | // Generates a string for a sequence of size at most BSIZE 69 | // and then wrties it to the output stream 70 | _seq S = arrayToCSVString(G.HE+offset,min(BSIZE,G.mh-offset)); 71 | file.write(S.A, S.n); 72 | S.del(); 73 | offset += BSIZE; 74 | } 75 | 76 | //writeArrayToStream< edge >(file,G.VE,G.mv); 77 | file.close(); 78 | } 79 | -------------------------------------------------------------------------------- /utils/gridGraph.C: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2011 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #include 23 | #include "parseCommandLine.h" 24 | #include "graphIO.h" 25 | #include "utils.h" 26 | #include "parallel.h" 27 | using namespace benchIO; 28 | using namespace std; 29 | 30 | template 31 | intT loc2d(intT n, intT i1, intT i2) { 32 | return ((i1 + n) % n)*n + (i2 + n) % n; 33 | } 34 | 35 | template 36 | edgeArray edge2DMesh(intT n) { 37 | intT dn = round(pow((float) n,1.0/2.0)); 38 | intT nn = dn*dn; 39 | intT nonZeros = 2*nn; 40 | edge *E = newA(edge,nonZeros); 41 | parallel_for (intT i=0; i < dn; i++) 42 | for (intT j=0; j < dn; j++) { 43 | intT l = loc2d(dn,i,j); 44 | E[2*l] = edge(l,loc2d(dn,i+1,j)); 45 | E[2*l+1] = edge(l,loc2d(dn,i,j+1)); 46 | } 47 | return edgeArray(E,nn,nn,nonZeros); 48 | } 49 | 50 | template 51 | intT loc3d(intT n, intT i1, intT i2, intT i3) { 52 | return ((i1 + n) % n)*n*n + ((i2 + n) % n)*n + (i3 + n) % n; 53 | } 54 | 55 | template 56 | edgeArray edge3DMesh(intT n) { 57 | intT dn = round(pow((float) n,1.0/3.0)); 58 | intT nn = dn*dn*dn; 59 | intT nonZeros = 3*nn; 60 | edge *E = newA(edge,nonZeros); 61 | parallel_for (intT i=0; i < dn; i++) 62 | for (intT j=0; j < dn; j++) 63 | for (intT k=0; k < dn; k++) { 64 | intT l = loc3d(dn,i,j,k); 65 | E[3*l] = edge(l,loc3d(dn,i+1,j,k)); 66 | E[3*l+1] = edge(l,loc3d(dn,i,j+1,k)); 67 | E[3*l+2] = edge(l,loc3d(dn,i,j,k+1)); 68 | } 69 | return edgeArray(E,nn,nn,nonZeros); 70 | } 71 | 72 | int parallel_main(int argc, char* argv[]) { 73 | commandLine P(argc,argv,"[-d {2,3}] n "); 74 | pair in = P.sizeAndFileName(); 75 | long n = in.first; 76 | char* fname = in.second; 77 | int dims = P.getOptionIntValue("-d", 2); 78 | edgeArray EA; 79 | if (dims == 2) 80 | EA = edge2DMesh(n); 81 | else if (dims == 3) 82 | EA = edge3DMesh(n); 83 | else 84 | P.badArgument(); 85 | graph G = graphFromEdges(EA, 1); 86 | EA.del(); 87 | writeGraphToFile(G, fname); 88 | G.del(); 89 | } 90 | -------------------------------------------------------------------------------- /utils/rMatGraph.C: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2011 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #include "parseCommandLine.h" 23 | #include "graphIO.h" 24 | #include "utils.h" 25 | #include "parallel.h" 26 | using namespace benchIO; 27 | using namespace std; 28 | 29 | double hashDouble(intT i) { 30 | return ((double) (hashInt((uintT)i))/((double) UINT_T_MAX));} 31 | 32 | template 33 | struct rMat { 34 | double a, ab, abc; 35 | intT n; 36 | uintT h; 37 | rMat(intT _n, intT _seed, 38 | double _a, double _b, double _c) { 39 | n = _n; a = _a; ab = _a + _b; abc = _a+_b+_c; 40 | h = hashInt((uintT)_seed); 41 | if(abc > 1) { cout << "in rMat: a + b + c add to more than 1\n"; abort();} 42 | if((1 << log2Up(n)) != n) { cout << "in rMat: n not a power of 2"; abort(); } 43 | } 44 | 45 | edge rMatRec(intT nn, intT randStart, intT randStride) { 46 | if (nn==1) return edge(0,0); 47 | else { 48 | edge x = rMatRec(nn/2, randStart + randStride, randStride); 49 | double r = hashDouble(randStart); 50 | if (r < a) return x; 51 | else if (r < ab) return edge(x.u,x.v+nn/2); 52 | else if (r < abc) return edge(x.u+nn/2, x.v); 53 | else return edge(x.u+nn/2, x.v+nn/2); 54 | } 55 | } 56 | 57 | edge operator() (intT i) { 58 | uintT randStart = hashInt((uintT)(2*i)*h); 59 | uintT randStride = hashInt((uintT)(2*i+1)*h); 60 | return rMatRec(n, randStart, randStride); 61 | } 62 | }; 63 | 64 | template 65 | edgeArray edgeRmat(intT n, intT m, intT seed, 66 | float a, float b, float c) { 67 | intT nn = (1 << log2Up(n)); 68 | rMat g(nn,seed,a,b,c); 69 | edge* E = newA(edge,m); 70 | parallel_for (intT i = 0; i < m; i++) 71 | E[i] = g(i); 72 | return edgeArray(E,nn,nn,m); 73 | } 74 | 75 | int parallel_main(int argc, char* argv[]) { 76 | commandLine P(argc,argv,"[-s] [-m ] [-r ] [-a ] [-b ] [-c ] n "); 77 | pair in = P.sizeAndFileName(); 78 | uintT n = in.first; 79 | char* fname = in.second; 80 | double a = P.getOptionDoubleValue("-a",.5); 81 | double b = P.getOptionDoubleValue("-b",.1); 82 | double c = P.getOptionDoubleValue("-c", b); 83 | uintT m = P.getOptionLongValue("-m", 10*n); 84 | intT seed = P.getOptionLongValue("-r", 1); 85 | bool sym = P.getOptionValue("-s"); 86 | edgeArray EA = edgeRmat(n, m, seed, a, b, c); 87 | graph G = graphFromEdges(EA, sym); 88 | EA.del(); 89 | writeGraphToFile(G, fname); 90 | G.del(); 91 | } 92 | -------------------------------------------------------------------------------- /utils/randHypergraph.C: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2011 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #include "parseCommandLine.h" 23 | #include "graphIO.h" 24 | #include "utils.h" 25 | #include "parallel.h" 26 | using namespace benchIO; 27 | using namespace std; 28 | 29 | struct edgeFirstCmp { 30 | bool operator() (edge e1, edge e2) { 31 | return e1.u < e2.u; 32 | } 33 | }; 34 | 35 | struct edgeSecondCmp { 36 | bool operator() (edge e1, edge e2) { 37 | return e1.v < e2.v; 38 | } 39 | }; 40 | 41 | template 42 | struct nonNeg {bool operator() (edge e) {return (e.u != UINT_T_MAX && e.v != UINT_T_MAX);}}; 43 | 44 | template 45 | hyperedgeArray hyperedgeRandom(long nv, long nh, long cardinality) { 46 | long numEdges = nh*cardinality; 47 | edge *VE = newA(edge,numEdges); 48 | edge *HE = newA(edge,numEdges); 49 | {parallel_for(long i=0;i(i,hashInt(offset)%nv); 53 | VE[offset] = edge(hashInt(offset)%nv,i); 54 | } 55 | //need to remove duplicates 56 | quickSort(VE+i*cardinality,cardinality,edgeFirstCmp()); 57 | quickSort(HE+i*cardinality,cardinality,edgeSecondCmp()); 58 | intT curr = HE[i*cardinality].v; 59 | for(long j=1;j *HE2 = newA(edge,numEdges); 67 | intT mh = sequence::filter(HE,HE2,numEdges,nonNeg()); 68 | free(HE); 69 | edge *VE2 = newA(edge,numEdges); 70 | intT mv = sequence::filter(VE,VE2,numEdges,nonNeg()); 71 | free(VE); 72 | //cout << mv << " " << mh << endl; 73 | return hyperedgeArray(VE2,HE2,nv,nh,mv,mh); 74 | } 75 | 76 | //Generates a symmetrized hypergraph with n vertices and m hyperedges, 77 | //each hyperedge containing c random vertices. Duplicate vertices in a 78 | //hyperedge are removed. 79 | int parallel_main(int argc, char* argv[]) { 80 | commandLine P(argc,argv,"[-nv ] [-nh ] [-c ] "); 81 | char* fname = P.getArgument(0); 82 | 83 | long nv = P.getOptionLongValue("-nv",100); 84 | long nh = P.getOptionLongValue("-nh", 10*nv); 85 | long cardinality = P.getOptionLongValue("-c", 3); 86 | 87 | hyperedgeArray EA = hyperedgeRandom(nv, nh, cardinality); 88 | hypergraph G = hypergraphFromHyperedges(EA); 89 | EA.del(); 90 | writeHypergraphToFile(G, fname); 91 | G.del(); 92 | } 93 | -------------------------------------------------------------------------------- /utils/randLocalGraph.C: -------------------------------------------------------------------------------- 1 | // This code is part of the Problem Based Benchmark Suite (PBBS) 2 | // Copyright (c) 2011 Guy Blelloch and the PBBS team 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a 5 | // copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights (to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included 13 | // in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #include "parseCommandLine.h" 23 | #include "graphIO.h" 24 | #include "utils.h" 25 | #include "parallel.h" 26 | using namespace benchIO; 27 | using namespace std; 28 | 29 | // Generates an undirected graph with n vertices with approximately degree 30 | // neighbors per vertex. 31 | // Edges are distributed so they appear to come from 32 | // a dim-dimensional space. In particular an edge (i,j) will have 33 | // probability roughly proportional to (1/|i-j|)^{(d+1)/d}, giving 34 | // separators of size about n^{(d-1)/d}. 35 | template 36 | edgeArray edgeRandomWithDimension(intT dim, intT nonZeros, intT numRows) { 37 | double degree = (double)nonZeros/numRows; 38 | edge *E = newA(edge,nonZeros); 39 | parallel_for (intT k=0; k < nonZeros; k++) { 40 | intT i = k / degree; 41 | intT j; 42 | if (dim==0) { 43 | uintT h = k; 44 | do { 45 | j = ((h = hashInt(h)) % numRows); 46 | if(j < 0 || j >= numRows) {cout << h << " " << j << endl; abort();} 47 | } while (j == i); 48 | } else { 49 | intT pow = dim+2; 50 | uintT h = k; 51 | do { 52 | while ((((h = hashInt(h)) % 1000003) < 500001)) pow += dim; 53 | j = (i + ((h = hashInt(h)) % (((long) 1) << pow))) % numRows; 54 | } while (j == i); 55 | } 56 | E[k].u = i; E[k].v = j; 57 | } 58 | return edgeArray(E,numRows,numRows,nonZeros); 59 | } 60 | 61 | //Generates a graph with n vertices and m edges, possibly with 62 | //duplicates, and then removes duplicate edges and symmetrizes the 63 | //graph. 64 | int parallel_main(int argc, char* argv[]) { 65 | commandLine P(argc,argv,"[-s] [-m ] [-d ] n "); 66 | pair in = P.sizeAndFileName(); 67 | long n = in.first; 68 | char* fname = in.second; 69 | int dim = P.getOptionIntValue("-d", 0); 70 | long m = P.getOptionLongValue("-m", 10*n); 71 | bool sym = P.getOptionValue("-s"); 72 | edgeArray EA = edgeRandomWithDimension(dim, m, n); 73 | graph G = graphFromEdges(EA, sym); 74 | EA.del(); 75 | writeGraphToFile(G, fname); 76 | G.del(); 77 | } 78 | -------------------------------------------------------------------------------- /utils/transpose.h: -------------------------------------------------------------------------------- 1 | ../ligra/transpose.h -------------------------------------------------------------------------------- /utils/wghSNAPtoAdj.C: -------------------------------------------------------------------------------- 1 | // This code is part of the project "Ligra: A Lightweight Graph Processing 2 | // Framework for Shared Memory", presented at Principles and Practice of 3 | // Parallel Programming, 2013. 4 | // Copyright (c) 2013 Julian Shun and Guy Blelloch 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights (to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | //Converts a weighted SNAP graph 26 | //(http://snap.stanford.edu/data/index.html) to Ligra weighted 27 | //adjacency graph format. Each line should contain three values---the 28 | //two endpoints followed by the weight. To symmetrize the graph, pass 29 | //the "-s" flag. For undirected graphs on SNAP, the "-s" flag must be 30 | //passed since each edge appears in only one direction 31 | 32 | #include "parseCommandLine.h" 33 | #include "graphIO.h" 34 | #include "parallel.h" 35 | 36 | int parallel_main(int argc, char* argv[]) { 37 | commandLine P(argc,argv,"[-s] "); 38 | char* iFile = P.getArgument(1); 39 | char* oFile = P.getArgument(0); 40 | bool sym = P.getOption("-s"); 41 | wghEdgeArray G = readWghSNAP(iFile); 42 | writeWghGraphToFile(wghGraphFromWghEdges(G,sym),oFile); 43 | } 44 | --------------------------------------------------------------------------------