#include "leak_detector.h" #include #include #include #include #include #include #include #include #include #include #if _WIN32 && NDEBUG && __BOOST #include #endif extern int passDone; #include "Cycle.h" #include "Arrays.h" #include "Array.h" #include "errors.h" #include "utils.h" #include "../VisualizerCalls/get_information.h" #include "../VisualizerCalls/SendMessage.h" #include "GraphCSR.h" using std::vector; using std::queue; using std::map; using std::set; using std::pair; using std::make_pair; using std::tuple; using std::string; using std::wstring; using namespace std::chrono; enum { WHITE, GREY, BLACK }; enum { CONFLICT_TYPE_1, CONFLICT_TYPE_2 }; #define MIN_CYCLE_DIM 2 #define PRINT_TIMES 1 namespace Distribution { template vType GraphCSR:: GetLocalVNum(const vType &V, bool &ifNew) { vType localV; if (V >= (vType)localIdx.size()) { localV = lastNumOfV; if ((vType)localIdx.size() <= V) { vType oldSize = (vType)localIdx.size(); localIdx.resize(V + 1); for (vType i = oldSize; i < (vType)localIdx.size(); ++i) localIdx[i] = -1; } localIdx[V] = localV; globalIdx.push_back(V); lastNumOfV++; ifNew = true; } else { if (localIdx[V] == -1) { localV = lastNumOfV; lastNumOfV++; localIdx[V] = localV; globalIdx.push_back(V); ifNew = true; } else { localV = localIdx[V]; ifNew = false; } } return localV; } template void GraphCSR:: AddEdgeToGraph(const vType &V1, const vType &V2, const wType &W, const attrType &attr, const bool &ifNew, const uint8_t linkType_) { if (!ifNew) { for (vType i = V1 + 1; i < numVerts + 1; ++i) neighbors[i]++; } else { if (neighbors.size() == 0) { neighbors.push_back(0); neighbors.push_back(1); } else neighbors.push_back(neighbors.back() + 1); numVerts++; } edges.insert(edges.begin() + neighbors[V1], V2); weights.insert(weights.begin() + neighbors[V1], W); attributes.insert(attributes.begin() + neighbors[V1], attr); linkType.insert(linkType.begin() + neighbors[V1], linkType_); } template void GraphCSR:: IncreaseWeight(const int &idx, const int &idxRev, const wType &W) { weights[idx] += W; weights[idxRev] += W; } template int GraphCSR:: CheckExist(const vType &V1, const vType &V2, const attrType &attr, const bool &ifNew, const uint8_t &linkTypeIn) { int ifExist = -1; if (!ifNew) { auto currNeigh = neighbors.data(); auto currEdges = edges.data(); auto currAttr = attributes.data(); auto currLinks = linkType.data(); for (vType i = currNeigh[V1]; i < currNeigh[V1 + 1]; ++i) { const vType k = currEdges[i]; if (k == V2 && attr == currAttr[i] && linkTypeIn == currLinks[i]) { ifExist = (int)i; break; } } } return ifExist; } //old algorithm without sort in the fly //TODO: need to update template void GraphCSR:: FindLoop(vector> &cycles, const vType V, const vType VPrev) { /*color[V] = GREY; for (vType i = neighbors[V]; i < neighbors[V + 1]; ++i) { vType k = edges[i]; if (k == VPrev) continue; if (color[k] == WHITE) { activeV.push_back(k); activeArcs.push_back(make_pair(weights[i], attributes[i])); FindLoop(cycles, k, V); activeV.pop_back(); activeArcs.pop_back(); } else if (color[k] == GREY && k == findFrom) { activeArcs.push_back(make_pair(weights[i], attributes[i])); auto idx = activeV.end(); auto idxVal = activeArcs.end(); Cycle newLoop; idx--; idxVal--; vType last = globalIdx[k]; while (*idx != k) { newLoop.AddArc(last, globalIdx[*idx], (*idxVal), 0); last = globalIdx[*idx]; idxVal--; idx--; } newLoop.AddArc(last, globalIdx[k], (*idxVal), 0); cycles.push_back(newLoop); //cyclesNum++; activeArcs.pop_back(); } } color[V] = WHITE;*/ } template void GraphCSR:: FindLoop(vector, Cycle>> &cycles, const vType V, const vType VPrev, const vector &numbers) { if (activeCounter > maxChainLen) return; color[V] = GREY; createNeededException(); for (vType i = neighbors[V]; i < neighbors[V + 1]; ++i) { vType k = edges[i]; if (k == VPrev) continue; if (color[k] == WHITE) { activeV[activeCounter] = k; activeE[activeCounter] = numbers[i]; activeArcs[activeCounter] = make_pair(weights[i], attributes[i]); activeCounter++; FindLoop(cycles, k, V, numbers); activeCounter--; } else if (color[k] == GREY && k == findFrom) { activeArcs[activeCounter] = make_pair(weights[i], attributes[i]); activeE[activeCounter] = numbers[i]; int idx = activeCounter - 1; int idxE = activeCounter; int idxVal = activeCounter; Cycle newLoop; vector shortBitLoop(numEdges / (2 * 32) + 1); vType last = k; //int dim = 0; while (activeV[idx] != k) { //dim++; const unsigned position = activeE[idxE]; shortBitLoop[position / 32] |= (1 << (position % 32)); newLoop.AddArc(activeV[idx], last, activeArcs[idxVal], position); last = activeV[idx]; idxVal--; idxE--; idx--; } //dim++; const unsigned position = activeE[idxE]; shortBitLoop[position / 32] |= (1 << (position % 32)); newLoop.AddArc(k, last, activeArcs[idxVal], position); const int currDimSize = newLoop.GetNumArcs(); if (currDimSize <= maxLoopDim) { auto itFound = cycles[currDimSize].find(shortBitLoop); if (itFound == cycles[currDimSize].end()) { usedMem += sizeof(unsigned) * shortBitLoop.capacity() + newLoop.getFullSize() + sizeof(void*); if (usedMem > maxAvailMemory && maxAvailMemory > 0) { printf("used %lld maxAvail %lld\n", usedMem, maxAvailMemory); fflush(NULL); throw -2; } cycles[currDimSize].insert(itFound, make_pair(shortBitLoop, newLoop)); } } } } color[V] = WHITE; } template void GraphCSR:: RemoveDuplicates(vector> &cycles) { auto timeR = steady_clock::now(); __spf_print(PRINT_TIMES, "PROF: RemoveDuplicates: start removing with %d cycles\n", (int)cycles.size()); vector, attrType>>> allUniqEdges(cycles.size()); //map sizes; vector parts; parts.push_back(0); int lastSize = cycles[0].GetNumArcs(); int maxSize = 0; for (vType i = 0; i < (vType)cycles.size(); ++i) { if (lastSize != cycles[i].GetNumArcs()) { parts.push_back(i); lastSize = cycles[0].GetNumArcs(); } //sizes[cycles[i].GetNumArcs()]++; maxSize = std::max(maxSize, cycles[i].GetNumArcs()); const vector> &currUniqArcs = cycles[i].GetArcs(); const vector &currUniqAttrArcs = cycles[i].GetAttributesArcs(); for (vType m = 0; m < (vType)currUniqArcs.size(); ++m) allUniqEdges[i].push_back(make_pair(currUniqArcs[m], currUniqAttrArcs[m])); //TODO: remove multiple arcs std::sort(allUniqEdges[i].begin(), allUniqEdges[i].end()); } parts.push_back((int)cycles.size()); /*for (map::iterator it = sizes.begin(); it != sizes.end(); it++) printf("%d: %d\n", it->first, it->second);*/ maxSize++; vector> uniqLoops(maxSize); __spf_print(PRINT_TIMES, "PROF: RemoveDuplicates: done inserting\n"); const vType part = vType((vType)cycles.size() * 0.1); auto timeT = steady_clock::now(); //#pragma omp parallel for schedule(dynamic) for (int p = 0; p < (int)parts.size() - 1; ++p) { for (vType it = parts[p]; it < parts[p + 1]; ++it) { if (it % part == 0 && PRINT_TIMES) { auto timeT1 = steady_clock::now(); __spf_print(PRINT_TIMES, "PROF: %d done with time %.3f sec\n", it, (duration_cast>(timeT1 - timeT)).count()); timeT = timeT1; } const int dimention = cycles[it].GetNumArcs(); if (uniqLoops[dimention].size() == 0) uniqLoops[dimention].push_back(it); else { const vector> &currArcs = cycles[it].GetArcs(); const vector &currAttrArcs = cycles[it].GetAttributesArcs(); bool uniq = true; for (int k = (int)uniqLoops[dimention].size() - 1; k >= 0; --k) { const vector, attrType>> &edgesUniq = allUniqEdges[uniqLoops[dimention][k]]; bool sameAll = true; for (vType m = 0; m < (vType)currArcs.size(); ++m) { pair revCurrArcs = make_pair(currArcs[m].second, currArcs[m].first); /*bool notFound = (edgesUniq.find(make_pair(currArcs[m], currAttrArcs[m])) == edgesUniq.end()) && (edgesUniq.find(make_pair(revCurrArcs, currAttrArcs[m])) == edgesUniq.end());*/ /*bool notFound = (find(edgesUniq.begin(), edgesUniq.end(), (make_pair(currArcs[m], currAttrArcs[m]))) == edgesUniq.end()) && (find(edgesUniq.begin(), edgesUniq.end(), (make_pair(revCurrArcs, currAttrArcs[m]))) == edgesUniq.end());*/ const pair, attrType> f1 = make_pair(currArcs[m], currAttrArcs[m]); const pair, attrType> f2 = make_pair(revCurrArcs, currAttrArcs[m]); bool notFound = true; for (int t = 0; t < (int)edgesUniq.size(); ++t) { if (edgesUniq[t] == f1 || edgesUniq[t] == f2) { notFound = false; break; } } if (notFound) { sameAll = false; break; } } if (sameAll) { uniq = false; break; } } if (uniq) uniqLoops[dimention].push_back(it); } } } vector> newLoops; for (vType k = 0; k < maxSize; ++k) for (vType i = 0; i < (vType)uniqLoops[k].size(); ++i) newLoops.push_back(cycles[uniqLoops[k][i]]); cycles = newLoops; __spf_print(PRINT_TIMES, "PROF: RemoveDuplicates: done removing with %d cycles, time %f sec\n", (int)cycles.size(), (duration_cast>(steady_clock::now() - timeR)).count()); } template bool GraphCSR:: findLink(const vType v1, pair &inGraphAttr1, const vType v2, pair &inGraphAttr2) { bool wasFound = false; for (int k = neighbors[v1]; k < neighbors[v1 + 1]; ++k) { const vType currV = edges[k]; if (currV == v2) { wasFound = true; inGraphAttr2 = attributes[k].second; inGraphAttr1 = attributes[k].first; break; } } if (wasFound) return true; else { for (int k = neighbors[v1]; k < neighbors[v1 + 1]; ++k) { if (color[edges[k]] == 1) continue; color[edges[k]] = 1; wasFound = findLink(edges[k], inGraphAttr1, v2, inGraphAttr2); if (wasFound) { inGraphAttr1 = attributes[k].first; break; } } } return wasFound; } pair Fx(const pair &x, const pair &F) { return make_pair(x.first * F.first, x.second * F.first + F.second); } static pair Fx(const pair &x, const pair &F) { return make_pair(x.first * F.first, x.second * F.first + F.second); } static pair Fx(const pair &x, const pair &F) { return make_pair(x.first * F.first, x.second * F.first + F.second); } template bool GraphCSR:: hasLinkWithTempate(const vType root, const Arrays &allArrays, bool increaseLink, int newValue) { set next = { root }; set done; bool found = false; while (next.size()) { set nextLoc; for (auto &v1 : next) { Array *tmp = allArrays.GetArrayByVertex(globalIdx[v1]); if (tmp) { if (tmp->IsTemplate()) { found = true; if (increaseLink) { if (neighbors[v1 + 1] - neighbors[v1] != 1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); const int k = neighbors[v1]; const vType edgeV = edges[k]; if (newValue == 0) attributes[k].first.first++; else attributes[k].first.first = newValue; bool done = false; for (int z = neighbors[edgeV]; z < neighbors[edgeV + 1]; ++z) { const vType currV = edges[z]; if (currV == v1) { if (newValue == 0) attributes[z].second.first++; else attributes[z].second.first = newValue; done = true; break; } } if (!done) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } break; } } for (int k = neighbors[v1]; k < neighbors[v1 + 1]; ++k) { const vType currV = edges[k]; auto it = done.find(currV); if (it == done.end()) { done.insert(it, currV); nextLoc.insert(currV); } } } next = nextLoc; } return found; } template pair GraphCSR:: findLinkWithTempate2(const vType v1, int &templV, Array *&templ, const Arrays &allArrays, set wasDone) { const pair nulPair = make_pair(0, 0); wasDone.insert(v1); bool wasFound = false; for (int k = neighbors[v1]; k < neighbors[v1 + 1]; ++k) { const vType currV = edges[k]; Array *tmp = allArrays.GetArrayByVertex(globalIdx[currV]); if (tmp) { if (tmp->IsTemplate()) { wasFound = true; templV = globalIdx[currV]; templ = tmp; return make_pair(attributes[k].second.first, attributes[k].second.second); //return make_pair(1.0f, 0.0f); } } } auto it = cacheLinks.find(v1); if (it == cacheLinks.end()) it = cacheLinks.insert(it, make_pair(v1, map>>())); for (int k = neighbors[v1]; k < neighbors[v1 + 1]; ++k) { if (wasDone.find(edges[k]) != wasDone.end()) continue; auto ruleCache = it->second.find(edges[k]); pair ruleToTemplate; if (ruleCache == it->second.end()) { ruleToTemplate = findLinkWithTempate2(edges[k], templV, templ, allArrays, wasDone); it->second.insert(ruleCache, make_pair(edges[k], make_tuple(templV, templ, ruleToTemplate))); } else { templV = std::get<0>(ruleCache->second); templ = std::get<1>(ruleCache->second); ruleToTemplate = std::get<2>(ruleCache->second); } if (ruleToTemplate != nulPair) { auto currAttribute = attributes[k]; pair left = currAttribute.first; pair right = currAttribute.second; // calculate transition pair X; X.first = right.first / left.first; left.first *= X.first; left.second *= X.first; X.second = right.second - left.second; return Fx(X, ruleToTemplate); } } return nulPair; } template int GraphCSR:: findDimNumLink(const vType v, const Array *to, const Arrays &allArrays, set &wasDone) const { int foundD = -1; int err = -1; for (int k = neighbors[v]; k < neighbors[v + 1]; ++k) { const vType currV = edges[k]; err = allArrays.GetDimNumber(to, globalIdx[currV], foundD); if (err != -1) break; } if (err != -1) return foundD; else { for (int k = neighbors[v]; k < neighbors[v + 1]; ++k) { const vType currV = edges[k]; if (wasDone.find(currV) != wasDone.end()) continue; wasDone.insert(v); foundD = findDimNumLink(currV, to, allArrays, wasDone); auto itToErase = wasDone.find(v); if (itToErase != wasDone.end()) wasDone.erase(itToErase); if (foundD != -1) break; } return foundD; } } template int GraphCSR:: AddToGraph(const vType &V1, const vType &V2, const wType &W, const attrType &attr, const uint8_t linkType) { if (V1 == V2) return -1; countRequestsToAdd++; vType localV1, localV2; bool ifNew1, ifNew2; localV1 = GetLocalVNum(V1, ifNew1); localV2 = GetLocalVNum(V2, ifNew2); attrType attrRev = make_pair(attr.second, attr.first); int idxExist = -1, idxExistRev = -1; idxExist = CheckExist(localV1, localV2, attr, ifNew1, linkType); idxExistRev = CheckExist(localV2, localV1, attrRev, ifNew2, linkType); bool ifExist = (idxExist != -1) && (idxExistRev != -1); int status = 0; if (!ifExist) { AddEdgeToGraph(localV1, localV2, W, attr, ifNew1, linkType); AddEdgeToGraph(localV2, localV1, W, attrRev, ifNew2, linkType); numEdges += 2; countMissToAdd++; } else { IncreaseWeight(idxExist, idxExistRev, W); status = 1; } return status; } template set GraphCSR:: FindTrees(vector &inTree, vector> &vertByTrees) { inTree.resize(numVerts); for (int i = 0; i < numVerts; ++i) inTree[i] = i; while (true) { bool mod = false; for (int i = 0; i < numVerts; ++i) { for (int k = neighbors[i]; k < neighbors[i + 1]; ++k) { const vType V = edges[k]; if (inTree[i] != inTree[V]) { mod = true; if (inTree[i] < inTree[V]) inTree[V] = inTree[i]; else inTree[i] = inTree[V]; } } } if (!mod) break; } set allTrees; for (int i = 0; i < numVerts; ++i) allTrees.insert(inTree[i]); map newIdx; int idx = 0; for (auto it = allTrees.begin(); it != allTrees.end(); ++it, ++idx) newIdx.insert(make_pair(*it, idx)); vertByTrees.resize(allTrees.size()); for (int i = 0; i < numVerts; ++i) vertByTrees[newIdx[inTree[i]]].push_back(i); return allTrees; } template void GraphCSR:: GetAllSimpleLoops(vector>> &cycles, bool needPrint, bool useSavedQuality) { //cyclesNum = 0; if (!useSavedQuality) treesQuality.clear(); cycles.clear(); color.resize(numVerts); activeCounter = 0; activeV = new vType[std::max(numVerts, numEdges) + 1]; activeE = new vType[std::max(numVerts, numEdges) + 1]; activeArcs = new pair[std::max(numVerts, numEdges) + 1]; map, wType, attrType>, int> uniqArcs; vector numbers(edges.size()); int num = 0; for (int i = 0; i < numVerts; ++i) { for (int k = neighbors[i]; k < neighbors[i + 1]; ++k) { const vType V = edges[k]; attrType reverse = make_pair(attributes[k].second, attributes[k].first); tuple, wType, attrType> tmp = std::make_tuple(make_pair(i, V), weights[k], attributes[k]); tuple, wType, attrType> tmp1 = std::make_tuple(make_pair(V, i), weights[k], reverse); auto it = uniqArcs.find(tmp); if (it == uniqArcs.end()) { numbers[k] = num; uniqArcs[tmp] = num; uniqArcs[tmp1] = num; num++; } else numbers[k] = it->second; } } int maxNum = 0; for (int i = 0; i < numEdges; ++i) maxNum = std::max(maxNum, numbers[i]); __spf_print(PRINT_TIMES && needPrint, "max num value = %d\n", maxNum); auto timeFind = steady_clock::now(); __spf_print(PRINT_TIMES && needPrint, "graph size: |V| = %d, |E| = %d, quality: [%d, %d]\n", numVerts, numEdges / 2, maxLoopDim, maxChainLen); if (maxNum + 1 != numEdges / 2 && maxNum != 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (numVerts == 0 && numEdges == 0) return; vector trees; vector> vertByTrees; set unqieTrees = FindTrees(trees, vertByTrees); __spf_print(PRINT_TIMES && needPrint, "trees count %d\n", (int)unqieTrees.size()); if (unqieTrees.size() == 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); vector, Cycle>>> cyclesTmp(unqieTrees.size()); usedMem = 0; for (int i = 0; i < unqieTrees.size(); ++i) { cyclesTmp[i].resize(numVerts + 1); usedMem += cyclesTmp[i].capacity() * sizeof(map, Cycle>); } __spf_print(PRINT_TIMES && needPrint, "cycles find started\n"); // find all cycles with dim >= 3 try { for (int t = 0; t < vertByTrees.size(); ++t) { const int vertArraySize = vertByTrees[t].size(); int wasMaxChainLen = maxChainLen; int wasMaxLoopDim = maxLoopDim; int newQuality = vertArraySize * maxLoopDim / 100; int newSpeed = vertArraySize * maxChainLen / 100; if (newQuality < 3) newQuality = 3; if (newSpeed < 3) newSpeed = 3; if (!useSavedQuality) { maxLoopDim = newQuality; maxChainLen = newSpeed; treesQuality.push_back(make_pair(maxLoopDim, maxChainLen)); } else { if (t < treesQuality.size()) { maxLoopDim = treesQuality[t].first; maxChainLen = treesQuality[t].second; } else { maxLoopDim = newQuality; maxChainLen = newSpeed; } } if (needPrint) printf("SAPFOR: [TREE %d], arrays num %d, maxLoopDim %d, maxChainLen %d\n", t, vertArraySize, maxLoopDim, maxChainLen); wstring treeM; if (needPrint) treeM = std::to_wstring(t + 1) + L"/" + std::to_wstring(vertByTrees.size()); for (int k = 0; k < vertByTrees[t].size(); ++k) { const vType i = vertByTrees[t][k]; const vType currentV = i; for (vType k = 0; k < numVerts; ++k) color[k] = WHITE; findFrom = currentV; /*#ifdef _WIN32 if (needPrint) { wstring vertexM = std::to_wstring(k + 1) + L"/" + std::to_wstring(vertByTrees[t].size()); sendMessage_2lvl(wstring(L"поиск простых циклов в графе, обработка дерева ") + wstring(treeM.begin(), treeM.end()) + L" вершины " + wstring(vertexM.begin(), vertexM.end())); } #endif*/ __spf_print(PRINT_TIMES && needPrint, "v (tree %d) = %d (with neighb %d) ", t, i, neighbors[i + 1] - neighbors[i]); activeV[activeCounter++] = currentV; FindLoop(cyclesTmp[t], currentV, currentV, numbers); activeCounter--; __spf_print(PRINT_TIMES && needPrint, "done with time %f\n", (duration_cast>(steady_clock::now() - timeFind)).count()); } maxChainLen = wasMaxChainLen; maxLoopDim = wasMaxLoopDim; } /*if (needPrint) sendMessage_2lvl(2);*/ } catch (int code) { if (code == -2) __spf_print(1, "OUT OF MEMORY: max avail %lld\n", maxAvailMemory); throw code; } int minSize = INT_MAX; int maxSize = 0; map countOfCycles; cycles.resize(vertByTrees.size()); for (int t = 0; t < vertByTrees.size(); ++t) { map countOfCyclesTree; for (int i = 0; i < cyclesTmp[t].size(); ++i) for (auto k = cyclesTmp[t][i].begin(); k != cyclesTmp[t][i].end(); ++k) { cycles[t].push_back(k->second); const int len = k->second.GetNumArcs(); minSize = std::min(minSize, len); maxSize = std::max(maxSize, len); { auto itF = countOfCycles.find(len); if (itF == countOfCycles.end()) itF = countOfCycles.insert(itF, make_pair(len, 0)); itF->second++; } { auto itF = countOfCyclesTree.find(len); if (itF == countOfCyclesTree.end()) itF = countOfCyclesTree.insert(itF, make_pair(len, 0)); itF->second++; } } __spf_print(PRINT_TIMES && needPrint, "FOR TREE %d\n", t); for (auto it = countOfCyclesTree.begin(); it != countOfCyclesTree.end(); ++it) __spf_print(PRINT_TIMES && needPrint, " found cycles with size %d = %d\n", it->first, it->second); } int allCycles = 0; for (auto it = countOfCycles.begin(); it != countOfCycles.end(); ++it) { __spf_print(PRINT_TIMES && needPrint, "found cycles with size %d = %d\n", it->first, it->second); allCycles += it->second; } delete []activeV; delete []activeE; delete []activeArcs; __spf_print(PRINT_TIMES && needPrint, "PROF: num cycles %d, time of find %f s\n", allCycles, (duration_cast>(steady_clock::now() - timeFind)).count()); __spf_print(PRINT_TIMES && needPrint, "PROF: minimum cycle size %d, maximum cycle size %d\n", minSize, maxSize); } template int GraphCSR:: SortLoopsBySize(vector> &cycles, bool needPrint) { auto timeR = steady_clock::now(); __spf_print(PRINT_TIMES && needPrint, "PROF: SortLoopsBySize: start\n"); int err = 0; vector> sortedLoops(cycles.size()); int currIdx = 0; for (vType g = MIN_CYCLE_DIM; g <= numVerts; ++g) { for (vType i = 0; i < (vType)cycles.size(); ++i) { if (g == cycles[i].GetNumArcs()) { sortedLoops[currIdx] = cycles[i]; currIdx++; } } } if (cycles.size() != currIdx) { char buf[256]; sprintf(buf, "Can not sort cycles"); addToGlobalBufferAndPrint(buf); err = -1; } else cycles = sortedLoops; __spf_print(PRINT_TIMES && needPrint, "PROF: SortLoopsBySize: end %f sec\n", (duration_cast>(steady_clock::now() - timeR)).count()); return err; } template int GraphCSR:: SortLoopsByWeight(vector> &cycles, bool needPrint) { auto timeR = steady_clock::now(); __spf_print(PRINT_TIMES && needPrint, "PROF: SortLoopsByWeight: start\n"); if (cycles.size() == 0) { __spf_print(PRINT_TIMES && needPrint, "PROF: SortLoopsByWeight: end %f sec\n", (duration_cast>(steady_clock::now() - timeR)).count()); return 0; } int err = 0; vector> sortedLoops; vType start = 0, end = 1; vType dim = MIN_CYCLE_DIM; for (vType i = 1; i < (vType)cycles.size(); ++i, ++end) { if (cycles[i].GetNumArcs() != dim) { sort(cycles.begin() + start, cycles.begin() + end); start = end; dim = cycles[i].GetNumArcs(); } } if (start != end) sort(cycles.begin() + start, cycles.begin() + end); __spf_print(PRINT_TIMES && needPrint, "PROF: SortLoopsByWeight: end %f sec\n", (duration_cast>(steady_clock::now() - timeR)).count()); return err; } #define WITH_CONFLICT_1 1 #define WITH_CONFLICT_2 1 template int GraphCSR:: GetConflictCycles(const vector> &cycles, const Arrays &allArrays, vector> &indexOfConflict, bool needPrint) { auto timeR = steady_clock::now(); __spf_print(PRINT_TIMES && needPrint, "PROF: GetConflictCycles: start\n"); int countOfConflict = 0; indexOfConflict.clear(); const set &arrays = allArrays.GetArrays(); vector cycleMarked(cycles.size()); for (vType i = 0; i < (vType)cycles.size(); ++i) { cycleMarked[i] = false; #if WITH_CONFLICT_1 const vector> &currArcs = cycles[i].GetArcs(); // check conflict of first type map> uniqInfo; for (int i1 = 0; i1 < (int)currArcs.size(); ++i1) { pair info; int ok = allArrays.GetInfoByVertex(globalIdx[currArcs[i1].first], info); if (ok == 0) { auto it = uniqInfo.find(info.second); if (it == uniqInfo.end()) uniqInfo.insert(it, make_pair(info.second, set())); it->second.insert(info.first); } ok = allArrays.GetInfoByVertex(globalIdx[currArcs[i1].second], info); if (ok == 0) { auto it = uniqInfo.find(info.second); if (it == uniqInfo.end()) uniqInfo.insert(it, make_pair(info.second, set())); it->second.insert(info.first); } } for (auto tmpIt = uniqInfo.begin(); tmpIt != uniqInfo.end(); ++tmpIt) { if (tmpIt->second.size() > 1) { indexOfConflict.push_back(make_pair(i, CONFLICT_TYPE_1)); countOfConflict++; cycleMarked[i] = true; break; } } #endif #if WITH_CONFLICT_2 // check conflict of second type if (!cycleMarked[i]) { const vector> &currArcs = cycles[i].GetArcs(); const vector &currAttributes = cycles[i].GetAttributesArcs(); // compare attributes on the same vertex for (int i1 = 0; i1 < (int)currArcs.size(); ++i1) { const pair &currArc = currArcs[i1]; const attrType &currAttrArc = currAttributes[i1]; pair toFindArc; attrType toFindAttrArc; vType sameVertex = -1; // find pair with same vertex for (int i2 = 0; i2 < (int)currArcs.size(); ++i2) { // if not currArc if (i2 != i1) { toFindArc = currArcs[i2]; toFindAttrArc = currAttributes[i2]; if (currArc.first == toFindArc.first || currArc.first == toFindArc.second) { sameVertex = currArc.first; if (currArc.first == toFindArc.second) swap(toFindAttrArc.first, toFindAttrArc.second); } else if (currArc.second == toFindArc.first || currArc.second == toFindArc.second) { sameVertex = currArc.second; if (currArc.second == toFindArc.first) swap(toFindAttrArc.first, toFindAttrArc.second); } if (sameVertex != -1) break; } } if (sameVertex == currArc.first && toFindAttrArc.first != currAttrArc.first || sameVertex == currArc.second && toFindAttrArc.second != currAttrArc.second) { indexOfConflict.push_back(make_pair(i, CONFLICT_TYPE_2)); cycleMarked[i] = true; countOfConflict++; break; } } } #endif } __spf_print(PRINT_TIMES && needPrint, "PROF: GetConflictCycles: end %f sec\n", (duration_cast>(steady_clock::now() - timeR)).count()); return countOfConflict; } #undef WITH_CONFLICT_1 #undef WITH_CONFLICT_2 template void GraphCSR:: RemoveMultipleArcsByWeights() { for (vType v = 0; v < numVerts; ++v) { map> tmp; for (vType k = neighbors[v]; k < neighbors[v + 1]; ++k) { const vType e = edges[k]; auto it = tmp.find(e); if (it == tmp.end()) tmp.insert(make_pair(e, make_pair(0, weights[k]))); else it->second.second = std::max(it->second.second, weights[k]); } for (vType k = neighbors[v]; k < neighbors[v + 1]; ++k) { const vType e = edges[k]; auto it = tmp.find(e); if (it->second.second == weights[k]) it->second.first++; } int removed = 0; for (vType k = neighbors[v], k1 = neighbors[v]; k < neighbors[v + 1]; ++k) { const vType e = edges[k1]; auto it = tmp.find(e); if (it->second.second != weights[k1] || (it->second.second == weights[k1] && it->second.first != 1)) { if (it->second.second == weights[k1]) it->second.first--; edges.erase(edges.begin() + k1); weights.erase(weights.begin() + k1); linkType.erase(linkType.begin() + k1); attributes.erase(attributes.begin() + k1); removed++; } else k1++; } for (int t = v + 1; t < numVerts + 1; ++t) neighbors[t] -= removed; } // correct graph information numEdges = (vType)edges.size(); } template bool GraphCSR:: checkFirstCoefOfNode(vType node) { bool ok = true; int firstCoef = attributes[neighbors[node]].first.first; for (vType k = neighbors[node] + 1; k < neighbors[node + 1]; ++k) { if (firstCoef != attributes[k].first.first) { ok = false; break; } } return ok; } template bool GraphCSR:: getOptimalBoundsForNode(vType nodeFrom, vType nodeTo, int &needBound, pair &bounds) { bool canCalc = true; bool initBound = false; bool initBounds = false; for (vType k = neighbors[nodeFrom]; k < neighbors[nodeFrom + 1]; ++k) { if (edges[k] == nodeTo) { if (initBound == false) { initBound = true; needBound = attributes[k].first.second; } else { if (needBound != attributes[k].first.second) { canCalc = false; break; } } } if (initBounds == false) { initBounds = true; bounds.first = bounds.second = attributes[k].first.second; } else { bounds.first = std::min(bounds.first, attributes[k].first.second); bounds.second = std::max(bounds.second, attributes[k].first.second); } } return canCalc; } static int calcNewBound(int needBound, pair &bounds) { if (needBound < bounds.first || needBound > bounds.second) { int dist1 = abs(needBound - bounds.first); int dist2 = abs(needBound - bounds.second); if (dist1 < dist2) return bounds.first; else return bounds.second; } else return needBound; } template void GraphCSR:: RemoveVerticesByWeight() { for (vType v = 0; v < numVerts; ++v) { int removed = 0; for (vType k = neighbors[v], k1 = neighbors[v]; k < neighbors[v + 1]; ++k) { if (weights[k1] == -1) { edges.erase(edges.begin() + k1); weights.erase(weights.begin() + k1); linkType.erase(linkType.begin() + k1); attributes.erase(attributes.begin() + k1); removed++; } else k1++; } for (int t = v + 1; t < numVerts + 1; ++t) neighbors[t] -= removed; } // correct graph information numEdges = (vType)edges.size(); } template void GraphCSR:: RemoveMultipleArcsOptimal() { vector toDel; for (vType v = 0; v < numVerts; ++v) { map>> numLinks; for (vType k = neighbors[v]; k < neighbors[v + 1]; ++k) { const vType e = edges[k]; if (v < e) { auto it = numLinks.find(e); if (it == numLinks.end()) it = numLinks.insert(it, make_pair(e, make_pair(0, vector()))); it->second.first++; it->second.second.push_back(k); } } for (auto it = numLinks.begin(); it != numLinks.end(); ++it) { //has multiple arcs if (it->second.first > 1) { const vector &idx = it->second.second; bool hasWW = false; int maxIdxW = -1; double maxW = -1; for (int k = 0; k < idx.size(); ++k) { if (linkType[idx[k]] == WW_link) hasWW = true; if (maxW < weights[idx[k]]) maxW = weights[idx[k]]; } //try to find non conflict arcs if (!hasWW) { if (checkFirstCoefOfNode(v) && checkFirstCoefOfNode(it->first)) { int needBoundL = 0, needBoundH = 0; pair boundsL, boundsH; bool canCalcL = getOptimalBoundsForNode(v, it->first, needBoundL, boundsL); bool canCalcH = getOptimalBoundsForNode(it->first, v, needBoundH, boundsH); if (canCalcL && canCalcH) { needBoundL = calcNewBound(needBoundL, boundsL); needBoundH = calcNewBound(needBoundH, boundsH); for (int k = 0; k < idx.size(); ++k) { int idxS = -1; for (int k = 0; k < idx.size(); ++k) { if (maxW == weights[idx[k]]) { idxS = k; break; } } for (int k = 0; k < idx.size(); ++k) { if (maxW == weights[idx[k]] && idxS == k) { for (vType n = neighbors[edges[idx[k]]]; n < neighbors[edges[idx[k]] + 1]; ++n) { if (edges[n] == v && attributes[n].first == attributes[idx[k]].second && attributes[n].second == attributes[idx[k]].first && linkType[n] == linkType[idx[k]]) { attributes[n].first.second = needBoundH; attributes[n].second.second = needBoundL; break; } } attributes[idx[k]].first.second = needBoundL; attributes[idx[k]].second.second = needBoundH; } else toDel.push_back(idx[k]); } } } else hasWW = true; } else hasWW = true; } //if has W-W links, set arc with maximum weight if (hasWW) { set uniqMaxIds; for (int k = 0; k < idx.size(); ++k) if (maxW == weights[idx[k]]) uniqMaxIds.insert(k); int exceptIdx = -1; if (uniqMaxIds.size() == 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); else if (uniqMaxIds.size() == 1) exceptIdx = *uniqMaxIds.begin(); else { int minDistToZero = 2147483647; // INT_MAX for (auto& elem : uniqMaxIds) { int sum = abs(0 - attributes[idx[elem]].second.second) + abs(0 - attributes[idx[elem]].first.second); if (minDistToZero > sum) { minDistToZero = sum; exceptIdx = elem; } } } if (exceptIdx < 0 || exceptIdx >= idx.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int k = 0; k < idx.size(); ++k) if (k != exceptIdx) toDel.push_back(idx[k]); //OLD ALGORITHM /*bool eqSet = false; for (int k = 0; k < idx.size(); ++k) { if (maxW == weights[idx[k]]) { if (eqSet == false) eqSet = true; else toDel.push_back(idx[k]); } else toDel.push_back(idx[k]); }*/ } } } } for (vType k = 0; k < toDel.size(); ++k) weights[toDel[k]] = -1; // add reverse arcs for (vType v = 0; v < numVerts; ++v) { for (vType k = neighbors[v]; k < neighbors[v + 1]; ++k) { if (weights[k] == -1 && v < edges[k]) { for (vType z = neighbors[edges[k]]; z < neighbors[edges[k] + 1]; ++z) { if (edges[z] == v && attributes[z].first == attributes[k].second && attributes[z].second == attributes[k].first && linkType[z] == linkType[k]) { weights[z] = -1; break; } } } } } RemoveVerticesByWeight(); } template int GraphCSR:: CreateGraphWiz(const char *fileName, const vector> &toDelArcs, const Arrays &allArrays, const bool onlyTree) { FILE *out = fopen(fileName, "w"); if (out == NULL) { char buf[256]; sprintf(buf, "can not open file %s\n", fileName); addToGlobalBufferAndPrint(buf); return -1; } set> dictDel; for (int i = 0; i < (int)toDelArcs.size(); ++i) { vType from = std::get<0>(toDelArcs[i]); vType to = std::get<1>(toDelArcs[i]); attrType attr = std::get<2>(toDelArcs[i]); attrType attrRev = make_pair(attr.second, attr.first); dictDel.insert(make_tuple(from, to, attr)); dictDel.insert(make_tuple(to, from, attrRev)); } fprintf(out, "graph G{\n"); const set& arrays = allArrays.GetArrays(); set::const_iterator it = arrays.begin(); for (; it != arrays.end(); it++) { const int dimSize = (*it)->GetDimSize(); const string arrayName = (*it)->GetName(); string verts = ""; bool allNotDefined = true; for (int i = 0; i < dimSize; ++i) { vType retVal; allArrays.GetVertNumber(*it, i, retVal); char buf[32]; if (retVal < localIdx.size() && retVal >= 0) { sprintf(buf, "%d", localIdx[retVal]); if (localIdx[retVal] != -1) allNotDefined = false; } else sprintf(buf, "%d", -1); verts += buf; verts += " "; } if (!allNotDefined) { fprintf(out, "subgraph cluster_%s {\n", arrayName.c_str()); for (int k = 0; k < dimSize; ++k) fprintf(out, "\"%s.%d\"\n", arrayName.c_str(), k); fprintf(out, "label = \"array %s (%s)\" \n", arrayName.c_str(), verts.c_str()); fprintf(out, "}\n"); } } for (vType i = 0; i < numVerts; ++i) { for (vType k = neighbors[i]; k < neighbors[i + 1]; ++k) { const vType i1 = edges[k]; const attrType attr = attributes[k]; if (i < i1) { const char *formatString; bool needToPrint = true; if (dictDel.find(make_tuple(i, i1, attr)) != dictDel.end()) { formatString = "\"%s\" -- \"%s\" [label=\"%s\", headlabel=\"[%d,%d]\", taillabel=\"[%d,%d]\", color=\"red\", minlen=2.0];\n"; if (onlyTree) needToPrint = false; } else formatString = "\"%s\" -- \"%s\" [label=\"%s\", headlabel=\"[%d,%d]\", taillabel=\"[%d,%d]\", minlen=2.0];\n"; if (needToPrint) { string v1; string v2; allArrays.GetNameByVertex(globalIdx[i], v1); allArrays.GetNameByVertex(globalIdx[i1], v2); char tmpP[32]; sprintf(tmpP, "%.1f ", weights[k]); string label = string(tmpP); if (linkType[k] == LinkType::RR_link) label += "RR"; else if (linkType[k] == LinkType::WR_link) label += "WR"; else if (linkType[k] == LinkType::WW_link) label += "WW"; else label += "UNK"; fprintf(out, formatString, v1.c_str(), v2.c_str(), label.c_str(), attr.first.first, attr.first.second, attr.second.first, attr.second.second); } } } } fprintf(out, "overlap=false\n"); fprintf(out, "}\n"); fclose(out); return 0; } template void GraphCSR:: RemovedEdges(const vector> &toDelArcs, const Arrays &allArrays) { set> dictDel; for (int i = 0; i < (int)toDelArcs.size(); ++i) { vType from = std::get<0>(toDelArcs[i]); vType to = std::get<1>(toDelArcs[i]); attrType attr = std::get<2>(toDelArcs[i]); attrType attrRev = make_pair(attr.second, attr.first); dictDel.insert(make_tuple(from, to, attr)); dictDel.insert(make_tuple(to, from, attrRev)); } int totalRemoved = 0; vector removed(numEdges); for (vType i = 0; i < numVerts; ++i) { int k = neighbors[i]; int k1 = neighbors[i]; int end = neighbors[i + 1]; int removed = 0; while (k1 != end) { const vType i1 = edges[k]; const attrType attr = attributes[k]; if (dictDel.find(make_tuple(i, i1, attr)) != dictDel.end()) { edges.erase(edges.begin() + k); weights.erase(weights.begin() + k); linkType.erase(linkType.begin() + k); attributes.erase(attributes.begin() + k); removed++; totalRemoved++; } else k++; k1++; } for (int t = i + 1; t < numVerts + 1; ++t) neighbors[t] -= removed; } //correct graph information numEdges = (vType)edges.size(); } template int GraphCSR:: GetAlignRuleForArray(Array *inputArray, const Arrays &allArrays, vector>> &assignedArrays) { vector arrayVerts; int err = allArrays.GetAllVertNumber(inputArray, arrayVerts); if (err != 0) return err; assignedArrays.resize(arrayVerts.size()); for (int i = 0; i < arrayVerts.size(); ++i) { const vType currV = localIdx[arrayVerts[i]]; int maxDimSize = 0; for (int k = neighbors[currV]; k < neighbors[currV + 1]; ++k) { const vType V1 = edges[k]; if (V1 >= globalIdx.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); Array *tmp = allArrays.GetArrayByVertex(globalIdx[V1]); if (tmp) { if (maxDimSize < tmp->GetDimSize()) { maxDimSize = tmp->GetDimSize(); assignedArrays[i].clear(); assignedArrays[i].push_back(make_tuple(tmp, globalIdx[V1], attributes[k])); } else if (maxDimSize == tmp->GetDimSize()) assignedArrays[i].push_back(make_tuple(tmp, globalIdx[V1], attributes[k])); } } } return 0; } template int GraphCSR:: GetAlignRuleWithTemplate(Array *inputArray, const Arrays &allArrays, vector>> &rules, const uint64_t regionId) { vector arrayVerts; int err = allArrays.GetAllVertNumber(inputArray, arrayVerts); if (err != 0) return err; rules.resize(arrayVerts.size()); if (inputArray->IsTemplate()) { std::vector vertsInGraph; allArrays.GetAllVertNumber(inputArray, vertsInGraph); if (vertsInGraph.size() != arrayVerts.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int i = 0; i < arrayVerts.size(); ++i) rules[i] = std::make_tuple(inputArray, vertsInGraph[i], make_pair(1, 0)); } else { for (int i = 0; i < arrayVerts.size(); ++i) { const vType currV = (arrayVerts[i] < localIdx.size()) ? localIdx[arrayVerts[i]] : -1; // if current vertex has links if (currV != -1) { pair rule = make_pair(0, 0); pair nul = rule; int alignDim = -1; Array *templ = NULL; set wasDone; if (hasLinkWithTempate(currV, allArrays, false)) { rule = findLinkWithTempate2(currV, alignDim, templ, allArrays, wasDone); if (rule != nul) { if ((int)rule.first.getDenominator() != 1 || rule.second.getDenominator() != 1) { __spf_print(1, "Can not find correct align rule for array '%s', found (%d/%d, %d/%d)\n", inputArray->GetShortName().c_str(), (int)rule.first.getNumerator(), (int)rule.first.getDenominator(), (int)rule.second.getNumerator(), (int)rule.second.getDenominator()); //TODO: need to correct //const int newValue = (rule.first.getDenominator() == rule.second.getDenominator()) ? rule.first.getDenominator() : 0; if (!hasLinkWithTempate(currV, allArrays, true)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return 101; } pair intRule = make_pair((int)rule.first.getNumerator(), (int)rule.second.getNumerator()); rules[i] = make_tuple(templ, alignDim, intRule); int dimNum = -1; int err = allArrays.GetDimNumber(templ, alignDim, dimNum); if (err == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); inputArray->AddLinkWithTemplate(i, dimNum, templ, intRule, regionId); } } } } } return 0; } template void GraphCSR:: FindLinksBetweenArrays(const Arrays &allArrays, const Array *from, const Array *to, vector &links) const { links.clear(); links.resize(from->GetDimSize()); vector vertNum; int err = allArrays.GetAllVertNumber(from, vertNum); if (err != 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int i = 0; i < from->GetDimSize(); ++i) { set wasDone; //no edges in graph if (localIdx[vertNum[i]] == -1) { links[i] = -1; continue; } int foundV = findDimNumLink(localIdx[vertNum[i]], to, allArrays, wasDone); links[i] = foundV; } } template void GraphCSR:: FindLinkWithMaxDim(const vType from, const Arrays &allArrays, pair &result, set &wasDone) { if (numVerts == 0) return; if (from >= localIdx.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); const vType v = localIdx[from]; if (v == -1) return; for (int k = neighbors[v]; k < neighbors[v + 1]; ++k) { const vType currV = edges[k]; if (wasDone.find(currV) != wasDone.end()) continue; wasDone.insert(v); if (currV >= globalIdx.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); Array *found = allArrays.GetArrayByVertex(globalIdx[currV]); if (found != NULL) { vType dimNumber = -1; int err = allArrays.GetDimNumber(found, globalIdx[currV], dimNumber); if (err != -1) { const pair &sizesRes = result.first->GetSizes()[result.second]; const pair &sizesFound = found->GetSizes()[dimNumber]; //calculate dimention sizes and compare if (sizesRes.second - sizesRes.first + 1 < sizesFound.second - sizesFound.first + 1) { result.first = found; result.second = dimNumber; } } } FindLinkWithMaxDim(globalIdx[currV], allArrays, result, wasDone); } } template int GraphCSR:: FindAllArraysTrees(map &trees, const Arrays &allArrays) { int treeCount = 1; set firstInit; map> wasDone; color.resize(numVerts); for (int i = 0; i < numVerts; ++i) color[i] = WHITE; vector qNextV; while (true) { int nextV = -1; if (qNextV.size() == 0) { for (int i = 0; i < numVerts; ++i) { if (color[i] == WHITE) { nextV = i; color[i] = BLACK; break; } } } else { nextV = qNextV.back(); qNextV.pop_back(); if (color[nextV] == BLACK) continue; else color[nextV] = BLACK; } if (nextV == -1) break; else { if (nextV >= globalIdx.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); Array *parentArray = allArrays.GetArrayByVertex(globalIdx[nextV]); if (parentArray == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (firstInit.find(parentArray) == firstInit.end()) { vector vertexes; int err = allArrays.GetAllVertNumber(parentArray, vertexes); if (err != 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int i = 0; i < vertexes.size(); ++i) { if (vertexes[i] < localIdx.size()) { const int idx = localIdx[vertexes[i]]; if (idx != nextV && idx != -1) qNextV.push_back(idx); } } firstInit.insert(parentArray); } for (int k = neighbors[nextV]; k < neighbors[nextV + 1]; ++k) { const vType currV = edges[k]; if (currV >= globalIdx.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); Array *currArray = allArrays.GetArrayByVertex(globalIdx[currV]); if (currArray == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); auto itParent = trees.find(parentArray); if (itParent == trees.end()) { itParent = trees.insert(itParent, make_pair(parentArray, treeCount)); treeCount++; } auto itAdd = trees.find(currArray); if (itAdd == trees.end()) trees.insert(itAdd, make_pair(currArray, itParent->second)); else { if (itParent->second != itAdd->second) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } auto itCurrCheck = wasDone.find(currArray); if (itCurrCheck == wasDone.end()) itCurrCheck = wasDone.insert(itCurrCheck, make_pair(currArray, set())); if (itCurrCheck->second.find(currV) == itCurrCheck->second.end()) { qNextV.push_back(currV); itCurrCheck->second.insert(currV); } } } } return treeCount - 1; } template void GraphCSR:: HighlightLinks() { if (hardLinksWasUp) return; wType sum; /*sum = 1.0; // count all RR_link weight for (int i = 0; i < weights.size(); ++i) { if (linkType[i] == RR_link) sum += weights[i]; } // and add it to all WR_link links for (int i = 0; i < weights.size(); ++i) { if (linkType[i] == WR_link) weights[i] += sum; } */ sum = 1.0; // count all RR_link and WR_link weight for (int i = 0; i < weights.size(); ++i) { if (linkType[i] == RR_link || linkType[i] == WR_link) sum += weights[i]; } // and add it to all WW_link links for (int i = 0; i < weights.size(); ++i) { if (linkType[i] == WW_link) weights[i] += sum; } hardLinksWasUp = true; } template bool GraphCSR:: SaveGraphToFile(FILE *file) { fwrite(&numVerts, sizeof(vType), 1, file); if (ferror(file)) return false; fwrite(&numEdges, sizeof(vType), 1, file); if (ferror(file)) return false; fwrite(&lastNumOfV, sizeof(vType), 1, file); if (ferror(file)) return false; auto tmpS = neighbors.size(); fwrite(&tmpS, sizeof(size_t), 1, file); fwrite(neighbors.data(), sizeof(vType), neighbors.size(), file); if (ferror(file)) return false; tmpS = edges.size(); fwrite(&tmpS, sizeof(size_t), 1, file); fwrite(edges.data(), sizeof(vType), edges.size(), file); if (ferror(file)) return false; tmpS = weights.size(); fwrite(&tmpS, sizeof(size_t), 1, file); fwrite(weights.data(), sizeof(wType), weights.size(), file); if (ferror(file)) return false; tmpS = linkType.size(); fwrite(&tmpS, sizeof(size_t), 1, file); fwrite(linkType.data(), sizeof(uint8_t), linkType.size(), file); if (ferror(file)) return false; tmpS = attributes.size(); fwrite(&tmpS, sizeof(size_t), 1, file); fwrite(attributes.data(), sizeof(attrType), attributes.size(), file); if (ferror(file)) return false; tmpS = localIdx.size(); fwrite(&tmpS, sizeof(size_t), 1, file); fwrite(localIdx.data(), sizeof(vType), localIdx.size(), file); if (ferror(file)) return false; tmpS = globalIdx.size(); fwrite(&tmpS, sizeof(size_t), 1, file); fwrite(globalIdx.data(), sizeof(vType), globalIdx.size(), file); if (ferror(file)) return false; return true; } template static inline void readStdVector(vector &T, const size_t size, FILE *file) { type *tmp = new type[size]; fread(tmp, sizeof(type), size, file); T.resize(size); for (int i = 0; i < size; ++i) T[i] = tmp[i]; delete []tmp; } template bool GraphCSR:: LoadGraphFromFile(FILE *file) { fread(&numVerts, sizeof(vType), 1, file); if (ferror(file)) return false; fread(&numEdges, sizeof(vType), 1, file); if (ferror(file)) return false; fread(&lastNumOfV, sizeof(vType), 1, file); if (ferror(file)) return false; size_t tmpS; fread(&(tmpS), sizeof(size_t), 1, file); readStdVector(neighbors, tmpS, file); if (ferror(file)) return false; fread(&(tmpS), sizeof(size_t), 1, file); readStdVector(edges, tmpS, file); if (ferror(file)) return false; fread(&(tmpS), sizeof(size_t), 1, file); readStdVector(weights, tmpS, file); if (ferror(file)) return false; fread(&(tmpS), sizeof(size_t), 1, file); readStdVector(linkType, tmpS, file); if (ferror(file)) return false; fread(&(tmpS), sizeof(size_t), 1, file); readStdVector(attributes, tmpS, file); if (ferror(file)) return false; fread(&(tmpS), sizeof(size_t), 1, file); readStdVector(localIdx, tmpS, file); if (ferror(file)) return false; fread(&(tmpS), sizeof(size_t), 1, file); readStdVector(globalIdx, tmpS, file); if (ferror(file)) return false; return true; } template vector GraphCSR:: GetAllAttributes(const int vert) const { vector retVal; if (localIdx.size() == 0 || vert >= localIdx.size()) return retVal; int locV = localIdx[vert]; if (locV < 0) return retVal; for (int z = neighbors[locV]; z < neighbors[locV + 1]; ++z) retVal.push_back(attributes[z]); return retVal; } template int GraphCSR:: CountOfConnected(const vType startV) const { std::vector inSet(numVerts); std::fill(inSet.begin(), inSet.end(), 0); vector next; next.reserve(numVerts); next.push_back(startV); inSet[startV] = 1; int count = 1; while (next.size()) { const vType V = next.back(); next.pop_back(); for (vType k = neighbors[V]; k < neighbors[V + 1]; ++k) { const vType toV = edges[k]; if (inSet[toV] == 0) { inSet[toV] = 1; count++; next.push_back(toV); } } } return count; } template int GraphCSR:: CountOfConnectedForArray(const vType startV) const { if (startV >= localIdx.size() || startV < 0) return 0; const int localV = localIdx[startV]; if (localV == -1) return 0; else return CountOfConnected(localV) - 1; } template pair GraphCSR:: MakeConnected(const vType startV, vector &inSet) const { int count = 0; int countE = 0; inSet.resize(numVerts); std::fill(inSet.begin(), inSet.end(), 0); vector next; next.reserve(numVerts); next.push_back(startV); inSet[startV] = 1; count = 1; while (next.size()) { const vType V = next.back(); next.pop_back(); for (vType k = neighbors[V]; k < neighbors[V + 1]; ++k) { const vType toV = edges[k]; if (inSet[toV] == 0) { inSet[toV] = 1; count++; next.push_back(toV); } } } for (int v = 0; v < numVerts; ++v) { for (vType k = neighbors[v]; k < neighbors[v + 1]; ++k) { const vType toV = edges[k]; if (inSet[toV]) countE++; } } return make_pair(count, countE / 2); } template static tuple makeReverse(const tuple &in) { vType from = std::get<0>(in); vType to = std::get<1>(in); attrType attr = std::get<2>(in); attrType attrRev = make_pair(attr.second, attr.first); return std::make_tuple(to, from, attrRev); } template vector> GraphCSR:: CreateMaximumSpanningTree() { set> selected; set tmp; for (int z = 0; z < numEdges; ++z) tmp.insert(edges[z]); int countOfRealV = tmp.size(); tmp.clear(); tuple maxEdge; wType startW = -1; set vInserted; while (vInserted.size() != countOfRealV) { startW = -1; for (auto &z : vInserted) { for (vType k = neighbors[z]; k < neighbors[z + 1]; ++k) { if (vInserted.find(edges[k]) != vInserted.end()) continue; if (startW < weights[k]) { startW = weights[k]; maxEdge = std::make_tuple(z, edges[k], attributes[k]); } } } if (startW != -1) { selected.insert(maxEdge); selected.insert(makeReverse(maxEdge)); vInserted.insert(std::get<0>(maxEdge)); vInserted.insert(std::get<1>(maxEdge)); } // next tree else { for (vType z = 0; z < numVerts; ++z) { for (vType k = neighbors[z]; k < neighbors[z + 1]; ++k) { if (vInserted.find(edges[k]) != vInserted.end()) continue; if (startW < weights[k]) { startW = weights[k]; maxEdge = std::make_tuple(z, edges[k], attributes[k]); } } } if (startW == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); else { selected.insert(maxEdge); selected.insert(makeReverse(maxEdge)); vInserted.insert(std::get<0>(maxEdge)); vInserted.insert(std::get<1>(maxEdge)); } } } vector> toDel; for (vType z = 0; z < numVerts; ++z) { for (vType k = neighbors[z]; k < neighbors[z + 1]; ++k) { if (selected.find(std::make_tuple(z, edges[k], attributes[k])) == selected.end()) toDel.push_back(std::make_tuple(z, edges[k], attributes[k])); } } return toDel; } template void GraphCSR:: RemoveAllEdgesFromGraph(const map>> &toDel, const Arrays& allArrays) { for (auto& arrayP : toDel) { Array* array = arrayP.first; checkNull(array, convertFileName(__FILE__).c_str(), __LINE__); if (!array->IsArray() && !array->IsTemplate()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); vector arrayVerts; int err = allArrays.GetAllVertNumber(array, arrayVerts); if (err != 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int i = 0; i < arrayVerts.size(); ++i) { const vType currV = localIdx[arrayVerts[i]]; // if current vertex has links if (currV != -1) { for (int k = neighbors[currV]; k < neighbors[currV + 1]; ++k) { const vType V2 = edges[k]; Array* arrayTo = allArrays.GetArrayByVertex(globalIdx[V2]); checkNull(array, convertFileName(__FILE__).c_str(), __LINE__); bool needToDel = true; if (arrayTo->IsArray()) { if (toDel.find(arrayTo) == toDel.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } else // tepmlate { if (toDel.find(arrayTo) == toDel.end()) needToDel = false; } //remove if (needToDel) weights[k] = -1; } } } } //remove from graph RemoveVerticesByWeight(); } template class GraphCSR; } #undef MIN_CYCLE_DIM #undef MAX_LOOP_DIM #undef PRINT_TIMES