Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get Neighbors implementation for Undirected and Directed Graphs with Tests #164

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions snap-core/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,43 @@ bool TUNGraph::IsOk(const bool& ThrowExcept) const {
return RetVal;
}

void TUNGraph::GetNeighbors(const int& NId, TIntV& NeighborsIdV){
//check if the node exists
AssertR(IsNode(NId), TStr::Fmt("NodeId %d does not exist", NId));

//get the snap node corresponding to nodeId
TNode& Node = GetNode(NId);

int neighborCount = Node.GetDeg();

NeighborsIdV.Gen(neighborCount, 0);

//go through the entire degree (as it is undirected) of this node
//NEdges -= Node.GetDeg();

for (int e = 0; e < Node.GetDeg(); e++) {

const int nbr = Node.GetNbrNId(e);

if (nbr == NId)
{
continue;
}

TNode& N = GetNode(nbr);

const int n = N.NIdV.SearchBin(NId);

IAssert(n != -1); // if NId points to N, then N also should point back

//add neighbor to neighbors list
if (n != -1) {
NeighborsIdV.Add(nbr);
}

}
}

// Print the graph in a human readable form to an output stream OutF.
void TUNGraph::Dump(FILE *OutF) const {
const int NodePlaces = (int) ceil(log10((double) GetNodes()));
Expand Down Expand Up @@ -434,6 +471,57 @@ bool TNGraph::IsOk(const bool& ThrowExcept) const {
return RetVal;
}

void TNGraph::GetNeighbors(const int& NId, TIntV& NeighborsIdV, bool outDegreeNeighbors){
//check if the node exists
AssertR(IsNode(NId), TStr::Fmt("NodeId %d does not exist", NId));

//get the snap node corresponding to nodeId
TNode& Node = GetNode(NId);

int neighborCount = 0;

if(outDegreeNeighbors){
neighborCount = Node.GetOutDeg();
}
else{
neighborCount = Node.GetInDeg();
}

NeighborsIdV.Gen(neighborCount, 0);

//go through the entire degree (as it is undirected) of this node
for (int e = 0; e < neighborCount; e++) {
int nbr;

if(outDegreeNeighbors){
nbr = Node.GetOutNId(e);
}
else{
nbr = Node.GetInNId(e);
}

if (nbr == NId)
{
continue;
}

TNode& N = GetNode(nbr);

if(outDegreeNeighbors){
const int n = N.InNIdV.SearchBin(NId);
if (n != -1) {
NeighborsIdV.Add(nbr);
}
}
else{
const int n = N.OutNIdV.SearchBin(NId);
if (n != -1) {
NeighborsIdV.Add(nbr);
}
}
}
}

void TNGraph::Dump(FILE *OutF) const {
const int NodePlaces = (int) ceil(log10((double) GetNodes()));
fprintf(OutF, "-------------------------------------------------\nDirected Node Graph: nodes: %d, edges: %d\n", GetNodes(), GetEdges());
Expand Down
5 changes: 5 additions & 0 deletions snap-core/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ class TUNGraph {
void Defrag(const bool& OnlyNodeLinks=false);
/// Checks the graph data structure for internal consistency. ##TUNGraph::IsOk
bool IsOk(const bool& ThrowExcept=true) const;
/// Fills in the neighbor list of the node in the provided vector ##TUNGraph::GetNeighbors
void GetNeighbors(const int& NId, TIntV& NeighborsIdV);
/// Print the graph in a human readable form to an output stream OutF.
void Dump(FILE *OutF=stdout) const;
/// Returns a small graph on 5 nodes and 5 edges. ##TUNGraph::GetSmallGraph
Expand Down Expand Up @@ -325,6 +327,7 @@ class TNGraph {
bool IsOutNId(const int& NId) const { return NodeHI.GetDat().IsOutNId(NId); }
/// Tests whether node with ID NId is a neighbor of the current node.
bool IsNbrNId(const int& NId) const { return IsOutNId(NId) || IsInNId(NId); }

friend class TNGraph;
};
/// Edge iterator. Only forward iteration (operator++) is supported.
Expand Down Expand Up @@ -470,6 +473,8 @@ class TNGraph {
void Defrag(const bool& OnlyNodeLinks=false);
/// Checks the graph data structure for internal consistency. ##TNGraph::IsOk
bool IsOk(const bool& ThrowExcept=true) const;
/// Fills in the neighbor list of the node in the provided vector ##TNGraph::GetNeighbors
void GetNeighbors(const int& NId, TIntV& NeighborsIdV, bool outDegreeNeighbors=true);
/// Print the graph in a human readable form to an output stream OutF.
void Dump(FILE *OutF=stdout) const;
/// Returns a small graph on 5 nodes and 6 edges. ##TNGraph::GetSmallGraph
Expand Down
34 changes: 34 additions & 0 deletions test/test-TNGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,39 @@ TEST(TNGraph, GetSmallGraph) {

EXPECT_EQ(1,Graph->IsOk());
EXPECT_EQ(0,Graph->Empty());
EXPECT_EQ(1,Graph->HasFlag(gfDirected));
}

// Test Neighbors
TEST(TNGraph, TestNeighbors) {
PNGraph Graph;

Graph = TNGraph::GetSmallGraph();

TIntV NeighborNodeIds;

Graph->GetNeighbors(0, NeighborNodeIds);

TNGraph::TNodeI NodeI = Graph->GetNI(0);
int degree = NodeI.GetOutDeg();
std::set<int> st;

for(int i=0;i<degree;i++){
std::cout<<"The "<<i<<"th neighbor of Node 1 is "<<NeighborNodeIds[i]<<std::endl;
st.insert(NeighborNodeIds[i]);
}

//only 2 neightbors should be present (0 & 2)
EXPECT_EQ(1, st.find(1) != st.end());
st.erase(1);

EXPECT_EQ(1, st.find(2) != st.end());
st.erase(2);

//check if null now
EXPECT_EQ(1, st.empty());

EXPECT_EQ(1,Graph->IsOk());

EXPECT_EQ(1,Graph->HasFlag(gfDirected));
}
35 changes: 35 additions & 0 deletions test/test-TUNGraph.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <gtest/gtest.h>

#include "Snap.h"
#include<set>

// Test the default constructor
TEST(TUNGraph, DefaultConstructor) {
Expand Down Expand Up @@ -288,5 +289,39 @@ TEST(TUNGraph, GetSmallGraph) {

EXPECT_EQ(1,Graph->IsOk());
EXPECT_EQ(0,Graph->Empty());
EXPECT_EQ(0,Graph->HasFlag(gfDirected));
}

// Test Neighbors
TEST(TUNGraph, TestNeighbors) {
PUNGraph Graph;

Graph = TUNGraph::GetSmallGraph();

TIntV NeighborNodeIds;

Graph->GetNeighbors(1, NeighborNodeIds);

TUNGraph::TNodeI NodeI = Graph->GetNI(1);
int degree = NodeI.GetDeg();
std::set<int> st;

for(int i=0;i<degree;i++){
std::cout<<"The "<<i<<"th neighbor of Node 1 is "<<NeighborNodeIds[i]<<std::endl;
st.insert(NeighborNodeIds[i]);
}

//only 2 neightbors should be present (0 & 2)
EXPECT_EQ(1, st.find(0) != st.end());
st.erase(0);

EXPECT_EQ(1, st.find(2) != st.end());
st.erase(2);

//check if null now
EXPECT_EQ(1, st.empty());

EXPECT_EQ(1,Graph->IsOk());

EXPECT_EQ(0,Graph->HasFlag(gfDirected));
}