Files
SAPFOR/Sapfor/_src/Distribution/GraphCSR.cpp

2303 lines
85 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include "../Utils/leak_detector.h"
#include <algorithm>
#include <string>
#include <assert.h>
#include <chrono>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <tuple>
#include <limits.h>
#if _WIN32 && NDEBUG && __BOOST
#include <boost/thread.hpp>
#endif
extern int passDone;
#include "Cycle.h"
#include "Arrays.h"
#include "Array.h"
#include "../Utils/errors.h"
#include "../Utils/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<typename vType, typename wType, typename attrType>
vType GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
IncreaseWeight(const int &idx, const int &idxRev, const wType &W)
{
weights[idx] += W;
weights[idxRev] += W;
}
template<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
FindLoop(vector<Cycle<vType, wType, attrType>> &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<vType, wType, attrType> 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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
FindLoop(vector<map<vector<unsigned>, Cycle<vType, wType, attrType>>> &cycles,
const vType V, const vType VPrev, const vector<vType> &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<vType, wType, attrType> newLoop;
vector<unsigned> 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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
RemoveDuplicates(vector<Cycle<vType, wType, attrType>> &cycles)
{
auto timeR = steady_clock::now();
__spf_print(PRINT_TIMES, "PROF: RemoveDuplicates: start removing with %d cycles\n", (int)cycles.size());
vector<vector<pair<pair<vType, vType>, attrType>>> allUniqEdges(cycles.size());
//map<int, int> sizes;
vector<int> 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<pair<vType, vType>> &currUniqArcs = cycles[i].GetArcs();
const vector<attrType> &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<int, int>::iterator it = sizes.begin(); it != sizes.end(); it++)
printf("%d: %d\n", it->first, it->second);*/
maxSize++;
vector<vector<vType>> 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<duration<double>>(timeT1 - timeT)).count());
timeT = timeT1;
}
const int dimention = cycles[it].GetNumArcs();
if (uniqLoops[dimention].size() == 0)
uniqLoops[dimention].push_back(it);
else
{
const vector<pair<vType, vType>> &currArcs = cycles[it].GetArcs();
const vector<attrType> &currAttrArcs = cycles[it].GetAttributesArcs();
bool uniq = true;
for (int k = (int)uniqLoops[dimention].size() - 1; k >= 0; --k)
{
const vector<pair<pair<vType, vType>, attrType>> &edgesUniq = allUniqEdges[uniqLoops[dimention][k]];
bool sameAll = true;
for (vType m = 0; m < (vType)currArcs.size(); ++m)
{
pair<vType, vType> 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<pair<vType, vType>, attrType> f1 = make_pair(currArcs[m], currAttrArcs[m]);
const pair<pair<vType, vType>, 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<Cycle<vType, wType, attrType>> 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<duration<double>>(steady_clock::now() - timeR)).count());
}
template<typename vType, typename wType, typename attrType>
bool GraphCSR<vType, wType, attrType>::
findLink(const vType v1, pair<int, int> &inGraphAttr1, const vType v2, pair<int, int> &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<int, int> Fx(const pair<int, int> &x, const pair<int, int> &F)
{
return make_pair(x.first * F.first, x.second * F.first + F.second);
}
static pair<double, double> Fx(const pair<double, double> &x, const pair<double, double> &F)
{
return make_pair(x.first * F.first, x.second * F.first + F.second);
}
static pair<RationalNum, RationalNum> Fx(const pair<RationalNum, RationalNum> &x, const pair<RationalNum, RationalNum> &F)
{
return make_pair(x.first * F.first, x.second * F.first + F.second);
}
template<typename vType, typename wType, typename attrType>
bool GraphCSR<vType, wType, attrType>::
hasLinkWithTempate(const vType root, const Arrays<vType> &allArrays, bool increaseLink, int newValue)
{
set<vType> next = { root };
set<vType> done;
bool found = false;
while (next.size())
{
set<vType> 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<typename vType, typename wType, typename attrType>
pair<RationalNum, RationalNum> GraphCSR<vType, wType, attrType>::
findLinkWithTempate2(const vType v1, int &templV, Array *&templ, const Arrays<vType> &allArrays, set<vType> wasDone)
{
const pair<RationalNum, RationalNum> 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<vType, tuple<int, Array*, pair<RationalNum, RationalNum>>>()));
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<RationalNum, RationalNum> 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<RationalNum, RationalNum> left = currAttribute.first;
pair<RationalNum, RationalNum> right = currAttribute.second;
// calculate transition
pair<RationalNum, RationalNum> 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<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
findDimNumLink(const vType v, const Array *to, const Arrays<vType> &allArrays, set<vType> &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<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
set<vType> GraphCSR<vType, wType, attrType>::
FindTrees(vector<vType> &inTree, vector<vector<vType>> &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<vType> allTrees;
for (int i = 0; i < numVerts; ++i)
allTrees.insert(inTree[i]);
map<vType, vType> 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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
GetAllSimpleLoops(vector<vector<Cycle<vType, wType, attrType>>> &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<wType, attrType>[std::max(numVerts, numEdges) + 1];
map<tuple<pair<vType, vType>, wType, attrType>, int> uniqArcs;
vector<vType> 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<pair<vType, vType>, wType, attrType> tmp = std::make_tuple(make_pair(i, V), weights[k], attributes[k]);
tuple<pair<vType, vType>, 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<vType> trees;
vector<vector<vType>> vertByTrees;
set<vType> 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<vector<map<vector<unsigned>, Cycle<vType, wType, attrType>>>> cyclesTmp(unqieTrees.size());
usedMem = 0;
for (int i = 0; i < unqieTrees.size(); ++i)
{
cyclesTmp[i].resize(numVerts + 1);
usedMem += cyclesTmp[i].capacity() * sizeof(map<vector<unsigned>, Cycle<vType, wType, attrType>>);
}
__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"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ") + wstring(treeM.begin(), treeM.end()) + L" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> " + 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<duration<double>>(steady_clock::now() - timeFind)).count());
}
maxChainLen = wasMaxChainLen;
maxLoopDim = wasMaxLoopDim;
}
if (needPrint)
sendMessage_2lvl(L"");
}
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<int, int> countOfCycles;
cycles.resize(vertByTrees.size());
for (int t = 0; t < vertByTrees.size(); ++t)
{
map<int, int> 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<duration<double>>(steady_clock::now() - timeFind)).count());
__spf_print(PRINT_TIMES && needPrint, "PROF: minimum cycle size %d, maximum cycle size %d\n", minSize, maxSize);
}
template<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
SortLoopsBySize(vector<Cycle<vType, wType, attrType>> &cycles, bool needPrint)
{
auto timeR = steady_clock::now();
__spf_print(PRINT_TIMES && needPrint, "PROF: SortLoopsBySize: start\n");
int err = 0;
vector<Cycle<vType, wType, attrType>> 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<duration<double>>(steady_clock::now() - timeR)).count());
return err;
}
template<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
SortLoopsByWeight(vector<Cycle<vType, wType, attrType>> &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<duration<double>>(steady_clock::now() - timeR)).count());
return 0;
}
int err = 0;
vector<Cycle<vType, wType, attrType>> 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<duration<double>>(steady_clock::now() - timeR)).count());
return err;
}
#define WITH_CONFLICT_1 1
#define WITH_CONFLICT_2 1
template<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
GetConflictCycles(const vector<Cycle<vType, wType, attrType>> &cycles,
const Arrays<vType> &allArrays,
vector<pair<int, int>> &indexOfConflict, bool needPrint)
{
auto timeR = steady_clock::now();
__spf_print(PRINT_TIMES && needPrint, "PROF: GetConflictCycles: start\n");
int countOfConflict = 0;
indexOfConflict.clear();
const set<Array*> &arrays = allArrays.GetArrays();
vector<bool> cycleMarked(cycles.size());
for (vType i = 0; i < (vType)cycles.size(); ++i)
{
cycleMarked[i] = false;
#if WITH_CONFLICT_1
const vector<pair<vType, vType>> &currArcs = cycles[i].GetArcs();
// check conflict of first type
map<Array*, set<vType>> uniqInfo;
for (int i1 = 0; i1 < (int)currArcs.size(); ++i1)
{
pair<int, Array*> 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<vType>()));
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<vType>()));
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<pair<vType, vType>> &currArcs = cycles[i].GetArcs();
const vector<attrType> &currAttributes = cycles[i].GetAttributesArcs();
// compare attributes on the same vertex
for (int i1 = 0; i1 < (int)currArcs.size(); ++i1)
{
const pair<vType, vType> &currArc = currArcs[i1];
const attrType &currAttrArc = currAttributes[i1];
pair<vType, vType> 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<duration<double>>(steady_clock::now() - timeR)).count());
return countOfConflict;
}
#undef WITH_CONFLICT_1
#undef WITH_CONFLICT_2
template<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
RemoveMultipleArcsByWeights()
{
for (vType v = 0; v < numVerts; ++v)
{
map<vType, pair<int, wType>> 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<typename vType, typename wType, typename attrType>
bool GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
bool GraphCSR<vType, wType, attrType>::
getOptimalBoundsForNode(vType nodeFrom, vType nodeTo, int &needBound, pair<int, int> &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<int, int> &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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
RemoveMultipleArcsOptimal()
{
vector<vType> toDel;
for (vType v = 0; v < numVerts; ++v)
{
map<vType, pair<int, vector<vType>>> 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<int>())));
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<vType> &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<int, int> 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<int> 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<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
CreateGraphWiz(const char *fileName, const vector<tuple<vType, vType, attrType>> &toDelArcs,
const Arrays<vType> &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<tuple<vType, vType, attrType>> 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<Array*>& arrays = allArrays.GetArrays();
set<Array*>::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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
RemovedEdges(const vector<tuple<vType, vType, attrType>> &toDelArcs, const Arrays<vType> &allArrays)
{
set<tuple<vType, vType, attrType>> 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<vType> 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<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
GetAlignRuleForArray(Array *inputArray, const Arrays<vType> &allArrays, vector<vector<tuple<Array*, vType, attrType>>> &assignedArrays)
{
vector<vType> 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<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
GetAlignRuleWithTemplate(Array *inputArray, const Arrays<vType> &allArrays, vector<tuple<Array*, vType, pair<int, int>>> &rules, const uint64_t regionId)
{
vector<vType> arrayVerts;
int err = allArrays.GetAllVertNumber(inputArray, arrayVerts);
if (err != 0)
return err;
rules.resize(arrayVerts.size());
if (inputArray->IsTemplate())
{
std::vector<vType> 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<RationalNum, RationalNum> rule = make_pair(0, 0);
pair<RationalNum, RationalNum> nul = rule;
int alignDim = -1;
Array *templ = NULL;
set<vType> 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<int, int> 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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
FindLinksBetweenArrays(const Arrays<vType> &allArrays, const Array *from, const Array *to, vector<int> &links) const
{
links.clear();
links.resize(from->GetDimSize());
vector<vType> 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<vType> 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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
FindLinkWithMaxDim(const vType from, const Arrays<vType> &allArrays, pair<Array*, int> &result, set<int> &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<int, int> &sizesRes = result.first->GetSizes()[result.second];
const pair<int, int> &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<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
FindAllArraysTrees(map<Array*, int> &trees, const Arrays<vType> &allArrays)
{
int treeCount = 1;
set<Array*> firstInit;
map<Array*, set<int>> wasDone;
color.resize(numVerts);
for (int i = 0; i < numVerts; ++i)
color[i] = WHITE;
vector<int> 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<vType> 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<int>()));
if (itCurrCheck->second.find(currV) == itCurrCheck->second.end())
{
qNextV.push_back(currV);
itCurrCheck->second.insert(currV);
}
}
}
}
return treeCount - 1;
}
template<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
bool GraphCSR<vType, wType, attrType>::
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<typename type>
static inline void readStdVector(vector<type> &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<typename vType, typename wType, typename attrType>
bool GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
vector<attrType> GraphCSR<vType, wType, attrType>::
GetAllAttributes(const int vert) const
{
vector<attrType> 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<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
CountOfConnected(const vType startV) const
{
std::vector<unsigned char> inSet(numVerts);
std::fill(inSet.begin(), inSet.end(), 0);
vector<vType> 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<typename vType, typename wType, typename attrType>
int GraphCSR<vType, wType, attrType>::
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<typename vType, typename wType, typename attrType>
pair<int, int> GraphCSR<vType, wType, attrType>::
MakeConnected(const vType startV, vector<unsigned char> &inSet) const
{
int count = 0;
int countE = 0;
inSet.resize(numVerts);
std::fill(inSet.begin(), inSet.end(), 0);
vector<vType> 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<typename vType, typename attrType>
static tuple<vType, vType, attrType> makeReverse(const tuple<vType, vType, attrType> &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<typename vType, typename wType, typename attrType>
vector<tuple<vType, vType, attrType>> GraphCSR<vType, wType, attrType>::
CreateMaximumSpanningTree()
{
set<tuple<vType, vType, attrType>> selected;
set<vType> tmp;
for (int z = 0; z < numEdges; ++z)
tmp.insert(edges[z]);
int countOfRealV = tmp.size();
tmp.clear();
tuple<vType, vType, attrType> maxEdge;
wType startW = -1;
set<vType> 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<tuple<vType, vType, attrType>> 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<typename vType, typename wType, typename attrType>
void GraphCSR<vType, wType, attrType>::
RemoveAllEdgesFromGraph(const map<Array*, vector<pair<int, int>>> &toDel, const Arrays<vType>& 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<vType> 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<int, double, attrType>;
}
#undef MIN_CYCLE_DIM
#undef MAX_LOOP_DIM
#undef PRINT_TIMES