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

Create isBipartiteGraph.hpp #465

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
87 changes: 87 additions & 0 deletions include/CXXGraph/Graph/Algorithm/isBipartiteGraph.hpp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests are failing. You need to include this file in CXXGraph/include/Graph/Graph.h

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/***********************************************************/
/*** ______ ____ ______ _ ***/
/*** / ___\ \/ /\ \/ / ___|_ __ __ _ _ __ | |__ ***/
/*** | | \ / \ / | _| '__/ _` | '_ \| '_ \ ***/
/*** | |___ / \ / \ |_| | | | (_| | |_) | | | | ***/
/*** \____/_/\_\/_/\_\____|_| \__,_| .__/|_| |_| ***/
/*** |_| ***/
/***********************************************************/
/*** Header-Only C++ Library for Graph ***/
/*** Representation and Algorithms ***/
/***********************************************************/
/*** Author: ZigRazor ***/
/*** E-Mail: [email protected] ***/
/***********************************************************/
/*** Collaboration: ----------- ***/
/***********************************************************/
/*** License: AGPL v3.0 ***/
/***********************************************************/

#ifndef __CXXGRAPH_CHECK_ODD_NODES_CYCLE_H__
#define __CXXGRAPH_CHECK_ODD_NODES_CYCLE_H__

#pragma once

#include "CXXGraph/Graph/Graph_decl.h"

namespace CXXGraph {

template <typename T>
class Graph {
public:
TopoSortResult<T> checkOddNodesCycleDir() const;

private:
void checkOddNodesCycleUtil(std::vector<int>& visited, std::vector<int>& chainNo,
int root, int cycleLength, bool &isBiPartite) const;
};

template <typename T>
TopoSortResult<T> Graph<T>::checkOddNodesCycleDir() const {
TopoSortResult<T> result;

// Check if the graph is undirected
if (isDirectedGraph()) {
result.errorMessage = ERR_UNDIR_GRAPH; // Error: Graph is directed
return result;
}

const auto nodeSet = Graph<T>::getNodeSet();
std::vector<int> visited(nodeSet.size(), 0);
std::vector<int> chainNo(nodeSet.size(), -1);
bool isBiPartite = true;

for (const auto& node : nodeSet) {
if (!visited[node->getId()]) {
visited[node->getId()] = 1;
checkOddNodesCycleUtil(visited, chainNo, node->getId(), 0, isBiPartite);
if (!isBiPartite) {
result.errorMessage = "The graph contains an odd-length cycle.";
return result;
}
}
}

result.success = true;
return result;
}

template <typename T>
void Graph<T>::checkOddNodesCycleUtil(std::vector<int>& visited, std::vector<int>& chainNo,
int root, int cycleLength, bool &isBiPartite) const {
chainNo[root] = cycleLength;
for (const auto& child : cachedAdjMatrix->find(root)) {
if (!visited[std::get<0>(child)->getId()]) {
visited[std::get<0>(child)->getId()] = 1;
checkOddNodesCycleUtil(visited, chainNo, std::get<0>(child)->getId(), cycleLength + 1, isBiPartite);
if (!isBiPartite) return;
} else if (chainNo[root] == chainNo[std::get<0>(child)->getId()]) {
isBiPartite = false;
return;
}
}
}

} // namespace CXXGraph

#endif // __CXXGRAPH_CHECK_ODD_NODES_CYCLE_H__
107 changes: 107 additions & 0 deletions test/BipartiteTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include <memory>

#include "CXXGraph/CXXGraph.hpp"
#include "gtest/gtest.h"

// Smart pointers alias
template <typename T>
using unique = std::unique_ptr<T>;
template <typename T>
using shared = std::shared_ptr<T>;

using std::make_shared;
using std::make_unique;

TEST(IsBipartiteTest, bipartite_graph) {
// Bipartite graph
CXXGraph::Node<int> node1("1", 1);
CXXGraph::Node<int> node2("2", 2);
CXXGraph::Node<int> node3("3", 3);
CXXGraph::Node<int> node4("4", 4);

CXXGraph::UndirectedEdge<int> edge1(1, node1, node2);
CXXGraph::UndirectedEdge<int> edge2(2, node1, node3);
CXXGraph::UndirectedEdge<int> edge3(3, node3, node4);
CXXGraph::UndirectedEdge<int> edge4(4, node2, node4);

CXXGraph::T_EdgeSet<int> edgeSet;
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge1));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge2));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge3));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge4));

CXXGraph::Graph<int> graph(edgeSet);

bool isBipartite = graph.isBipartite();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method doesn't exist, you didn't define it. Maybe you'd want to rename the methods in the header file.

ASSERT_EQ(isBipartite, true); // This graph is bipartite
}

TEST(IsBipartiteTest, non_bipartite_graph) {
// Non-bipartite graph with odd cycle
CXXGraph::Node<int> node1("1", 1);
CXXGraph::Node<int> node2("2", 2);
CXXGraph::Node<int> node3("3", 3);

CXXGraph::UndirectedEdge<int> edge1(1, node1, node2);
CXXGraph::UndirectedEdge<int> edge2(2, node2, node3);
CXXGraph::UndirectedEdge<int> edge3(3, node3, node1); // Forms a cycle of 3 nodes

CXXGraph::T_EdgeSet<int> edgeSet;
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge1));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge2));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge3));

CXXGraph::Graph<int> graph(edgeSet);

bool isBipartite = graph.isBipartite();
ASSERT_EQ(isBipartite, false); // This graph has an odd-length cycle, so it's not bipartite
}

TEST(IsBipartiteTest, empty_graph) {
// Empty graph
CXXGraph::T_EdgeSet<int> edgeSet;
CXXGraph::Graph<int> graph(edgeSet);

bool isBipartite = graph.isBipartite();
ASSERT_EQ(isBipartite, true); // An empty graph is trivially bipartite
}

TEST(IsBipartiteTest, single_node_graph) {
// Single node graph (trivially bipartite)
CXXGraph::Node<int> node1("1", 1);
CXXGraph::T_EdgeSet<int> edgeSet;
CXXGraph::Graph<int> graph(edgeSet);

bool isBipartite = graph.isBipartite();
ASSERT_EQ(isBipartite, true); // A graph with a single node is bipartite
}

TEST(IsBipartiteTest, complex_bipartite_graph) {
// More complex bipartite graph
CXXGraph::Node<int> node1("1", 1);
CXXGraph::Node<int> node2("2", 2);
CXXGraph::Node<int> node3("3", 3);
CXXGraph::Node<int> node4("4", 4);
CXXGraph::Node<int> node5("5", 5);
CXXGraph::Node<int> node6("6", 6);

CXXGraph::UndirectedEdge<int> edge1(1, node1, node2);
CXXGraph::UndirectedEdge<int> edge2(2, node1, node3);
CXXGraph::UndirectedEdge<int> edge3(3, node4, node5);
CXXGraph::UndirectedEdge<int> edge4(4, node4, node6);
CXXGraph::UndirectedEdge<int> edge5(5, node2, node4);
CXXGraph::UndirectedEdge<int> edge6(6, node3, node5);

CXXGraph::T_EdgeSet<int> edgeSet;
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge1));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge2));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge3));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge4));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge5));
edgeSet.insert(make_shared<CXXGraph::UndirectedEdge<int>>(edge6));

CXXGraph::Graph<int> graph(edgeSet);

bool isBipartite = graph.isBipartite();
ASSERT_EQ(isBipartite, true); // This graph is bipartite
}
Loading