2303 lines
85 KiB
C++
2303 lines
85 KiB
C++
|
|
#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
|