Skip to content

Commit

Permalink
Cleaned up some code and naming things and started implementing max m…
Browse files Browse the repository at this point in the history
…atching algorithm on bipartite graph.
  • Loading branch information
rowanG077 committed Nov 11, 2018
1 parent 30bdfc6 commit 0ea3be8
Show file tree
Hide file tree
Showing 18 changed files with 112 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Checks: '*,-fuchsia-default-arguments,-google-readability-namespace-comments,-hicpp-deprecated-headers,-llvm-header-guard,-llvm-namespace-comment,-modernize-deprecated-headers,-fuchsia-overloaded-operator'
Checks: '*,-google-runtime-references,-fuchsia-default-arguments,-google-readability-namespace-comments,-hicpp-deprecated-headers,-llvm-header-guard,-llvm-namespace-comment,-modernize-deprecated-headers,-fuchsia-overloaded-operator'
WarningsAsErrors: ''
HeaderFilterRegex: '.*'
AnalyzeTemporaryDtors: false
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ if(${CODE})
set(PROJECT_LANGUAGES ${PROJECT_LANGUAGES} C CXX)
endif()

project(box_nesting
project(BoxNesting
VERSION 1.0.0
DESCRIPTION "Algorithms and Datastructures practicum 1 box nesting algorithm"
LANGUAGES ${PROJECT_LANGUAGES})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <box_nesting/Box.hpp>
#include <graph/Graph.hpp>
#pragma once

#include <BoxNesting/Box.hpp>
#include <Graph/Graph.hpp>

/**
* @brief Contains code for the boxnesting problem
Expand All @@ -25,7 +27,7 @@ class Algorithm
* @return uint64_t the number of visible boxes after running the nesting
* algorithm
*/
[[nodiscard]] uint16_t runAlgorithm(const std::vector<Box>& boxes);
[[nodiscard]] uint16_t runAlgorithm(const std::vector<Box>& boxes) const;

/**
* @brief function that appends data to an empty graph given a set of boxes.
Expand All @@ -38,7 +40,20 @@ class Algorithm
*
* @return Graph::Graph<Box> the graph of type BoxNesting::Box
*/
[[nodiscard]] Graph::Graph<Box> createGraphFromBoxes(const std::vector<Box>& boxes);
[[nodiscard]] Graph::Graph<Box> createGraphFromBoxes(const std::vector<Box>& boxes) const;

private:
/**
* @brief Run the kuhn algorithm
*
* @param graph The total graph
* @param vertex The index of the vertex in the graph its neighbours
* @param used Contains whether a vertex in the left part of the graph was used
* @param pairs Contains which pairs are allready made
* @return Whether pairs could be made
*/
bool kuhn(
const Graph::Graph<Box>& graph, uint16_t vertex, std::vector<bool>& used, std::vector<int32_t>& pairs) const;
};

} // namespace BoxNesting
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#include <istream>
#include <vector>

#include <box_nesting/Box.hpp>
#include <box_nesting/ParserError.hpp>
#include <BoxNesting/Box.hpp>
#include <BoxNesting/ParserError.hpp>

/**
* @brief Contains code for the boxnesting problem
Expand Down
File renamed without changes.
18 changes: 10 additions & 8 deletions include/graph/Graph.hpp → include/Graph/Graph.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#ifndef GRAPH_HPP
#define GRAPH_HPP
#pragma once

#include <graph/Vertex.hpp>
#include <Graph/Vertex.hpp>

#include <unordered_map>
#include <unordered_set>
Expand All @@ -19,9 +18,14 @@ namespace Graph
template<class T> struct AdjacencyList
{
/**
* @brief Contains a vertex and the indices of its neighbors
* @brief The vertex for this adjacencyList
*/
std::pair<Vertex<T>, std::vector<std::uint16_t>> content;
Vertex<T> vertex;

/**
* @brief The vertices the head vertex can travel to via an edge.
*/
std::vector<std::uint16_t> edges;
};

/**
Expand Down Expand Up @@ -74,6 +78,4 @@ template<class T> class Graph

} // namespace Graph

#include <graph/Graph.ipp>

#endif // GRAPH_HPP
#include <Graph/Graph.ipp>
30 changes: 14 additions & 16 deletions include/graph/Graph.ipp → include/Graph/Graph.ipp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <graph/Graph.hpp>
#include <Graph/Graph.hpp>

#include <algorithm>
#include <exception>
Expand All @@ -9,50 +9,48 @@ namespace Graph
template <class T>
void Graph<T>::addVertex(const Vertex<T>& vertex)
{
adjacencyList.emplace_back(
AdjacencyList<T>{std::make_pair(vertex, std::vector<std::uint16_t>())}
);
this->adjacencyList.emplace_back(AdjacencyList<T>{vertex, std::vector<std::uint16_t>()});
}

template <class T>
void Graph<T>::addEdge(const Vertex<T>& v1, const Vertex<T>& v2)
{
auto e1 = std::find_if(this->adjacencyList.begin(), this->adjacencyList.end(),
[&](const AdjacencyList<T>& e) { return e.content.first == v1; });
[&](const AdjacencyList<T>& e) { return e.vertex == v1; });
auto e2 = std::find_if(this->adjacencyList.begin(), this->adjacencyList.end(),
[&](const AdjacencyList<T>& e) { return e.content.first == v2; });
[&](const AdjacencyList<T>& e) { return e.vertex == v2; });

if (e1 == adjacencyList.end()) {
if (e1 == this->adjacencyList.end()) {
throw std::logic_error("addEdge, v1 vertex does not exist in adjacency list of graph.");
}
if (e2 == adjacencyList.end()) {
if (e2 == this->adjacencyList.end()) {
throw std::logic_error("addEdge, v2 vertex does not exist in adjacency list of graph.");
}

e1->content.second.emplace_back(e2 - this->adjacencyList.begin());
e2->content.second.emplace_back(e1 - this->adjacencyList.begin());
e1->edges.emplace_back(e2 - this->adjacencyList.begin());
e2->edges.emplace_back(e1 - this->adjacencyList.begin());
}

template <class T>
bool Graph<T>::isEdgeBetween(const Vertex<T> &v1, const Vertex<T> &v2) const
{
auto e1 = std::find_if(this->adjacencyList.begin(), this->adjacencyList.end(),
[&](const AdjacencyList<T>& e) { return e.content.first == v1; });
[&](const AdjacencyList<T>& e) { return e.vertex == v1; });
auto e2 = std::find_if(this->adjacencyList.begin(), this->adjacencyList.end(),
[&](const AdjacencyList<T>& e) { return e.content.first == v2; });
[&](const AdjacencyList<T>& e) { return e.vertex == v2; });

if (e1 == adjacencyList.end()) {
if (e1 == this->adjacencyList.end()) {
throw std::logic_error("isEdgeBetween, v1 vertex does not exist in adjacency list of graph.");
}
if (e2 == adjacencyList.end()) {
if (e2 == this->adjacencyList.end()) {
throw std::logic_error("isEdgeBetween, v2 vertex does not exist in adjacency list of graph.");
}

auto requiredIndex = e2 - this->adjacencyList.begin();

const auto founditerator = std::find(e1->content.second.begin(), e1->content.second.end(), requiredIndex);
const auto founditerator = std::find(e1->edges.begin(), e1->edges.end(), requiredIndex);

return founditerator != e1->content.second.end();
return founditerator != e1->edges.end();
}

template <class T>
Expand Down
7 changes: 2 additions & 5 deletions include/graph/Vertex.hpp → include/Graph/Vertex.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef VERTEX_HPP
#define VERTEX_HPP
#pragma once

#include <vector>

Expand Down Expand Up @@ -76,6 +75,4 @@ template<class T> struct VertexHash

} // namespace Graph

#include <graph/Vertex.ipp>

#endif // VERTEX_HPP
#include <Graph/Vertex.ipp>
2 changes: 1 addition & 1 deletion include/graph/Vertex.ipp → include/Graph/Vertex.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Vertex<T>::Vertex(T con): id(++idCounter), content(std::move(con)), visited(fals
template <class T>
bool Vertex<T>::operator==(const Vertex<T>& rhs) const
{
return id == rhs.getId();
return this->id == rhs.getId();
}

template <class T>
Expand Down
48 changes: 44 additions & 4 deletions src/Algorithm.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,57 @@
#include <algorithm>
#include <vector>

#include <box_nesting/Algorithm.hpp>
#include <BoxNesting/Algorithm.hpp>

/**
* @brief Contains code for the boxnesting problem
*/
namespace BoxNesting
{
uint16_t Algorithm::runAlgorithm(const std::vector<Box>& boxes)
uint16_t Algorithm::runAlgorithm(const std::vector<Box>& boxes) const
{
const auto graph = createGraphFromBoxes(boxes);

// TO-DO: implementation of Berge's lemma
// n is the amount of vertices in the left part and the right part
// of the bipartite graph. We know this is exactly the amount of vertices
// divided by two since we for each box we create one vertex
// in the left part of the graph and one in the right part of the graph

// since we know graph size doesn't exceed uint16_t we can cast here safely
auto n = static_cast<uint16_t>(graph.getAdjacencyList().size() / 2);

// contains indices of the vertices in right part of the graph
// on marked edges
std::vector<int32_t> pairs(n, -1);
// Contains whether a vertex
std::vector<bool> used(n, false);

// iterate through vertices of the left side
// of the bipartate graph
for (uint16_t i = 0; i < n; ++i) {
fill(used.begin(), used.end(), false);
kuhn(graph, i, used, pairs);
}

return 0;
}

Graph::Graph<Box> Algorithm::createGraphFromBoxes(const std::vector<Box>& boxes)
bool Algorithm::kuhn(
const Graph::Graph<Box>& graph, uint16_t vertex, std::vector<bool>& used, std::vector<int32_t>& pairs) const
{
if (used[vertex]) {
return false;
}
used[vertex] = true;
const auto& neighbours = graph.getAdjacencyList().at(vertex).edges;
for (uint16_t i = 0; i < neighbours.size(); ++i) {
pairs[i] = 1;
}

return true;
}

Graph::Graph<Box> Algorithm::createGraphFromBoxes(const std::vector<Box>& boxes) const
{
Graph::Graph<Box> graph;

Expand All @@ -29,6 +64,11 @@ Graph::Graph<Box> Algorithm::createGraphFromBoxes(const std::vector<Box>& boxes)
[](const auto& b) { return Graph::Vertex<Box>(b); });

// Add two distinct vertices to the graph for each box
// by constructing the graph this way we know that
// the first half of the adjacency list belongs to
// to the left side of the bipartite graph
// and the second half of the adjacency list belongs
// to the right side of the bipartite graph
for (const auto& v : leftVertices) {
graph.addVertex(v);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Box.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <box_nesting/Box.hpp>
#include <BoxNesting/Box.hpp>

#include <algorithm>
#include <sstream>
Expand Down
2 changes: 1 addition & 1 deletion src/Parser.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <box_nesting/Parser.hpp>
#include <BoxNesting/Parser.hpp>

#include <climits>
#include <regex>
Expand Down
18 changes: 9 additions & 9 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
#include <box_nesting/Algorithm.hpp>
#include <box_nesting/Parser.hpp>
#include <box_nesting/version.hpp>
#include <BoxNesting/Algorithm.hpp>
#include <BoxNesting/Parser.hpp>
#include <BoxNesting/version.hpp>

#include <cstdlib>
#include <iostream>

void printVersion()
{
std::cout << "program info:" << std::endl
<< "\tname: " << BOX_NESTING_NAME << std::endl
<< "\tdescription: " << BOX_NESTING_DESCRIPTION << std::endl
<< "\tauthor: " << BOX_NESTING_AUTHOR << std::endl
<< "\tversion: " << BOX_NESTING_VERSION << std::endl
<< "\tmail: " << BOX_NESTING_MAIL << std::endl
<< "\tcopyright: " << BOX_NESTING_COPYRIGHT << std::endl;
<< "\tname: " << BOXNESTING_NAME << std::endl
<< "\tdescription: " << BOXNESTING_DESCRIPTION << std::endl
<< "\tauthor: " << BOXNESTING_AUTHOR << std::endl
<< "\tversion: " << BOXNESTING_VERSION << std::endl
<< "\tmail: " << BOXNESTING_MAIL << std::endl
<< "\tcopyright: " << BOXNESTING_COPYRIGHT << std::endl;
}

void printHelp(const std::string& progName)
Expand Down
6 changes: 3 additions & 3 deletions test/Algorithm.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <box_nesting/Algorithm.hpp>
#include <BoxNesting/Algorithm.hpp>
#include <catch2/catch.hpp>

#define CATCH_CONFIG_MAIN
Expand All @@ -24,8 +24,8 @@ SCENARIO("Running the 'graph creation from a set of boxes' function")
for (const auto& list1 : graph.getAdjacencyList()) {
for (const auto& list2 : graph.getAdjacencyList()) {
// An edge means the box is nestable
auto& v1 = list1.content.first;
auto& v2 = list2.content.first;
auto& v1 = list1.vertex;
auto& v2 = list2.vertex;
if (graph.isEdgeBetween(v1, v2)) {
auto isNestable = v1.getContent().isNestable(v2.getContent())
|| v2.getContent().isNestable(v1.getContent());
Expand Down
2 changes: 1 addition & 1 deletion test/Box.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <box_nesting/Box.hpp>
#include <BoxNesting/Box.hpp>
#include <catch2/catch.hpp>

SCENARIO("Box construction and valid side lengths")
Expand Down
4 changes: 2 additions & 2 deletions test/Graph.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include <box_nesting/Box.hpp>
#include <BoxNesting/Box.hpp>
#include <Graph/Graph.hpp>
#include <catch2/catch.hpp>
#include <graph/Graph.hpp>

SCENARIO("A graph of boxes add edged and check if no vertex has an edge to itsself", "[Graph]")
{
Expand Down
2 changes: 1 addition & 1 deletion test/Parser.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <box_nesting/Parser.hpp>
#include <BoxNesting/Parser.hpp>
#include <catch2/catch.hpp>

#include <cstddef>
Expand Down

0 comments on commit 0ea3be8

Please sign in to comment.