#ifndef GCG_GRAPHALGORITHMS_DEF_H_
#define GCG_GRAPHALGORITHMS_DEF_H_
#include "graph/graphalgorithms.h"
#include <vector>
#include <algorithm>
#include <map>
#include <iostream>
#include "stdlib.h"
#include "graph/graph_tclique.h"
#include "graph/graph_gcg.h"
using std::vector;
namespace gcg {
template <typename T>
double GraphAlgorithms<T>::cutoff = 0.0;
template<class T>
double GraphAlgorithms<T>::computeSoed(
Hypergraph<T>& graph
)
{
SCIP_Real soed = 0.0;
size_t nedges = graph.getNHyperedges();
vector<int> partition = vector<int>(graph.getPartition());
for( size_t i = 0; i < nedges; ++i )
{
vector<int> nodes = graph.getHyperedgeNodes(i);
for( auto &it : nodes)
{
it = partition[it];
}
auto end = std::unique(nodes.begin(), nodes.end());
if( end - nodes.begin() > 1)
soed += ( end - nodes.begin())*graph.getHyperedgeWeight(i);
}
return soed;
}
template<class T>
double GraphAlgorithms<T>::computeMincut(
Hypergraph<T>& graph
)
{
SCIP_Real mincut = 0.0;
size_t nedges = graph.getNHyperedges();
vector<int> partition = vector<int>(graph.getPartition());
for( size_t i = 0; i < nedges; ++i )
{
vector<int> nodes = graph.getHyperedgeNodes(i);
for( auto &it : nodes)
{
it = partition[it];
}
auto end = std::unique(nodes.begin(), nodes.end());
if( end - nodes.begin() > 1)
mincut += graph.getHyperedgeWeight(i);
}
return mincut;
}
template<class T>
double GraphAlgorithms<T>::computekMetric(
Hypergraph<T>& graph
)
{
SCIP_Real kmetric = 0.0;
size_t nedges = graph.getNHyperedges();
vector<int> partition = vector<int>(graph.getPartition());
for( size_t i = 0; i < nedges; ++i )
{
vector<int> nodes = graph.getHyperedgeNodes(i);
for( auto &it : nodes)
{
it = partition[it];
}
auto end = std::unique(nodes.begin(), nodes.end());
kmetric += ( end - nodes.begin() -1)*graph.getHyperedgeWeight(i);
}
return kmetric;
}
template<class T>
std::vector<int> GraphAlgorithms<T>::dbscan(
Graph<GraphGCG>& graph,
double eps,
int minPts
)
{
int n_nodes = graph.getNNodes();
std::vector<bool> visited(n_nodes, false);
std::vector<bool> is_core(n_nodes, false);
std::vector<int> labels(n_nodes, -1);
int curr_cluster = -1;
for(int i = 0; i < n_nodes; i++)
{
if(visited[i])
{
continue;
}
visited[i] = true;
std::vector<std::pair<int, double> > NeighborPts_row = graph.getNeighborWeights(i); std::vector<int> NeighborPts; for(int j = 0; j < (int)NeighborPts_row.size(); j++)
{
if(NeighborPts_row[j].second <= eps)
{
NeighborPts.push_back(NeighborPts_row[j].first);
}
}
if((int)NeighborPts.size() < minPts)
{
labels[i] = -1; }
else {
curr_cluster++;
expandCluster(graph, visited, is_core, labels, i, NeighborPts, curr_cluster, eps, minPts);
}
}
for(int i = 0; i < n_nodes; i++)
{
if(is_core[i])
{
continue;
}
std::vector<std::pair<int, double> > NeighborPts_row = graph.getNeighborWeights(i); for(int j = 0; j < (int)NeighborPts_row.size(); j++)
{
if(NeighborPts_row[j].second <= eps && is_core[NeighborPts_row[j].first])
{
labels[i] = labels[NeighborPts_row[j].first];
break;
}
}
}
return labels;
}
template<class T>
void GraphAlgorithms<T>::expandCluster(
Graph<T>& graph,
std::vector<bool>& visited,
std::vector<bool>& is_core,
std::vector<int>& labels,
int point,
std::vector<int>& NeighborPts,
int curr_cluster,
double eps,
int minPts
)
{
labels[point] = curr_cluster;
is_core[point] = true;
for(int i = 0; i < (int)NeighborPts.size(); i++)
{
int neighbor = NeighborPts[i];
if(!visited[neighbor])
{
visited[neighbor] = true;
std::vector<std::pair<int, double> > NeighborPts_tmp_row = graph.getNeighborWeights(neighbor); std::vector<int> NeighborPts_tmp; for(int j = 0; j < (int)NeighborPts_tmp_row.size(); j++)
{
if(NeighborPts_tmp_row[j].second <= eps)
{
NeighborPts_tmp.push_back(NeighborPts_tmp_row[j].first);
}
}
if((int)NeighborPts_tmp.size() >= minPts)
{
NeighborPts.insert(NeighborPts.end(), NeighborPts_tmp.begin(), NeighborPts_tmp.end());
}
}
if(labels[neighbor] < 0)
{
labels[neighbor] = curr_cluster;
is_core[neighbor] = true;
}
}
}
template<class T>
std::vector<int> GraphAlgorithms<T>::mst(
Graph<GraphGCG>& graph,
double _cutoff,
int minPts
)
{
cutoff = _cutoff;
int nnodes = graph.getNNodes();
std::vector<void*> edges(graph.getNEdges());
graph.getEdges(edges);
vector<EdgeGCG> resultMST(nnodes-1);
int e = 0; unsigned int j = 0;
sort(edges.begin(), edges.end(), weightComp);
vector<subset> subsetsmst(nnodes);
for (int v = 0; v < nnodes; ++v)
{
subsetsmst[v].parent = v;
subsetsmst[v].rank = 0;
}
while (e < nnodes - 1)
{
if(j == edges.size()) break;
EdgeGCG next_edge = *(EdgeGCG *)(edges[j++]);
assert(next_edge.src < graph.getNNodes());
assert(next_edge.dest < graph.getNNodes());
int x = mstfind(subsetsmst, next_edge.src); int y = mstfind(subsetsmst, next_edge.dest);
if (x != y)
{
resultMST[e++] = next_edge;
mstunion(subsetsmst, x, y);
}
}
resultMST.resize(e);
resultMST.erase(std::remove_if(resultMST.begin(), resultMST.end(), cutoffif), resultMST.end());
std::vector<int> labels(nnodes, -1);
std::vector<subset> subsetscomp(nnodes);
for (int v = 0; v < nnodes; ++v)
{
subsetscomp[v].parent = v;
subsetscomp[v].rank = 0;
}
for(unsigned int edge_it = 0; edge_it < resultMST.size(); edge_it++)
{
auto edge = resultMST[edge_it];
assert(edge.src < graph.getNNodes());
assert(edge.dest < graph.getNNodes());
mstunion(subsetscomp, edge.src, edge.dest);
}
for(int i = 0; i < nnodes; i++)
{
labels[i] = mstfind(subsetscomp, i);
}
std::map<int,int> labelcount;
for(int i = 0; i < nnodes; i++)
{
labelcount[labels[i]]++;
}
for(int i = 0; i < nnodes; i++)
{
if(labelcount[labels[i]] < minPts)
labels[i] = -1;
}
return labels;
}
template<class T>
bool GraphAlgorithms<T>::cutoffif(EdgeGCG &a)
{
return a.weight > cutoff;
}
template<class T>
int GraphAlgorithms<T>::weightComp(const void* a, const void* b)
{
const EdgeGCG* a1 = static_cast<const EdgeGCG*>(a);
const EdgeGCG* b1 = static_cast<const EdgeGCG*>(b);
return a1->weight < b1->weight;
}
template<class T>
int GraphAlgorithms<T>::mstfind(std::vector<subset>& subsets, int i)
{
if (subsets[i].parent != i)
subsets[i].parent = mstfind(subsets, subsets[i].parent);
return subsets[i].parent;
}
template<class T>
void GraphAlgorithms<T>::mstunion(std::vector<subset>& subsets, int x, int y)
{
int xroot = mstfind(subsets, x);
int yroot = mstfind(subsets, y);
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
template<class T>
std::vector<int> GraphAlgorithms<T>::mcl(
Graph<GraphGCG>& graph,
int& stoppedAfter,
double inflatefac,
int maxiters,
int expandfac
)
{
#ifdef WITH_GSL
graph.initMCL();
graph.colL1Norm();
graph.prune();
int i = 0;
for(; i < maxiters; i++)
{
graph.inflate(inflatefac);
graph.expand(expandfac);
graph.prune();
if(graph.stopMCL(i))
{
break;
}
}
assert(i > 6);
stoppedAfter = i;
std::vector<int> res = graph.getClustersMCL();
graph.clearMCL();
return res;
#else
return vector<int>();
#endif
}
}
#endif