-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
336 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#include "HopcroftKarpAlgorithm.hpp" | ||
|
||
#include <algorithm> | ||
#include <queue> | ||
|
||
/** | ||
* @brief Contains code for the boxnesting problem | ||
*/ | ||
namespace BoxNesting | ||
{ | ||
HopcroftKarpAlgorithm::HopcroftKarpAlgorithm(const std::vector<Box>& boxes) | ||
{ | ||
// In the boxes case left and right vertices are the same amount since | ||
// they are the amount of boxes | ||
this->leftVerticesCount = static_cast<int16_t>(boxes.size()); | ||
this->rightVerticesCount = this->leftVerticesCount; | ||
|
||
this->NILL = this->leftVerticesCount; | ||
|
||
this->pairsLeft = std::vector<int16_t>(this->leftVerticesCount + 1, this->NILL); | ||
this->pairsRight = std::vector<int16_t>(this->rightVerticesCount + 1, this->NILL); | ||
this->distances = std::vector<int16_t>(this->leftVerticesCount + 1, 0); | ||
|
||
this->graph.resize(this->leftVerticesCount); | ||
|
||
for (int16_t i = 0; i < this->leftVerticesCount; ++i) { | ||
this->graph[i].reserve(this->rightVerticesCount); | ||
for (int16_t j = 0; j < this->rightVerticesCount; ++j) { | ||
if (boxes[i] < boxes[j]) { | ||
this->graph[i].emplace_back(j); | ||
} | ||
} | ||
this->graph[i].shrink_to_fit(); | ||
} | ||
} | ||
|
||
int16_t HopcroftKarpAlgorithm::runAlgorithm() const | ||
{ | ||
// We have the same amount of visible boxes as there | ||
// are vertices in the left part of the bipartite graph | ||
// for each valid match (i.e. a box can nest inside another box) | ||
// we remove a visible box | ||
int16_t visibleBoxes = this->leftVerticesCount; | ||
|
||
while (bfs()) | ||
{ | ||
// Find a free vertex | ||
for (int16_t i = 0; i < leftVerticesCount; ++i) | ||
{ | ||
if (pairsLeft[i] == this->NILL && this->dfs(i)) | ||
{ | ||
--visibleBoxes; | ||
} | ||
} | ||
} | ||
|
||
return visibleBoxes; | ||
} | ||
|
||
bool HopcroftKarpAlgorithm::dfs(int16_t vertex) const | ||
{ | ||
if (vertex == this->NILL) | ||
{ | ||
return true; | ||
} | ||
|
||
auto sz = this->graph[vertex].size(); | ||
for (int16_t j = 0; j < sz; ++j) | ||
{ | ||
// Follow the distances set by BFS | ||
if (this->distances[this->pairsRight[j]] == this->distances[vertex] + 1) | ||
{ | ||
// If dfs for pair of v also returns | ||
// true | ||
if (dfs(this->pairsRight[j])) | ||
{ | ||
this->pairsRight[j] = vertex; | ||
this->pairsLeft[vertex] = j; | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
// If there is no augmenting path beginning with u. | ||
this->distances[vertex] = this->INFINITE; | ||
return false; | ||
} | ||
|
||
bool HopcroftKarpAlgorithm::bfs() const | ||
{ | ||
std::queue<int16_t> queue; | ||
|
||
// First layer of vertices (set distance as 0) | ||
for (int16_t i = 0; i < this->leftVerticesCount; ++i) | ||
{ | ||
// If this is a free vertex, add it to queue | ||
if (this->pairsLeft[i] == this->NILL) | ||
{ | ||
this->distances[i] = 0; | ||
queue.push(i); | ||
} | ||
// Else set distance as infinite | ||
// so that this vertex | ||
// is considered next time | ||
else | ||
{ | ||
this->distances[i] = this->INFINITE; | ||
} | ||
} | ||
|
||
// Initialize distance to NIL as infinite | ||
this->distances[this->NILL] = this->INFINITE; | ||
|
||
// the queue can only contain vertices off the left part of the bipartite graph | ||
while (!queue.empty()) | ||
{ | ||
// Dequeue a vertex | ||
auto i = queue.front(); | ||
queue.pop(); | ||
|
||
// If this node is not NIL and can provide a shorter path to NIL | ||
if (this->distances[i] < this->distances[this->NILL]) | ||
{ | ||
// Get all adjacent vertices of the dequeued vertex u | ||
auto sz = this->graph[i].size(); | ||
for (int16_t j = 0; j < sz; ++j) | ||
{ | ||
// If pair of v is not considered so far | ||
// (v, pairV[V]) is not yet explored edge. | ||
if (this->distances[this->pairsRight[j]] == this->INFINITE) | ||
{ | ||
// Consider the pair and add it to queue | ||
this->distances[this->pairsRight[j]] = this->distances[i] + 1; | ||
queue.push(this->pairsRight[j]); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// If we could come back to NIL using alternating path of distinct | ||
// vertices then there is an augmenting path | ||
return this->distances[this->NILL] != this->INFINITE; | ||
} | ||
|
||
} // namespace BoxNesting |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#pragma once | ||
|
||
#include "Box.hpp" | ||
|
||
#include <cstdint> | ||
#include <limits> | ||
#include <vector> | ||
|
||
/** | ||
* @brief Contains code for the boxnesting problem | ||
*/ | ||
namespace BoxNesting | ||
{ | ||
/** | ||
* @brief class that contains the boxnesting algorithm | ||
*/ | ||
class HopcroftKarpAlgorithm | ||
{ | ||
public: | ||
/** | ||
* @brief Deleted default constructor | ||
*/ | ||
HopcroftKarpAlgorithm() = delete; | ||
|
||
/** | ||
* @brief Construct a new Algorithm object | ||
* | ||
* @param boxes The boxes to generate the internal graph for | ||
*/ | ||
explicit HopcroftKarpAlgorithm(const std::vector<Box>& boxes); | ||
|
||
/** | ||
* @brief function that runs the boxNesting algorithm and returns the number | ||
* of visible boxes | ||
* | ||
* @param boxes the set of boxes to be nested | ||
* @return the number of visible boxes after running the nesting | ||
* algorithm | ||
*/ | ||
[[nodiscard]] int16_t runAlgorithm() const; | ||
|
||
private: | ||
bool bfs() const; | ||
bool dfs(int16_t vertex) const; | ||
|
||
private: | ||
/** | ||
* @brief adjacencyList of left vertices generated from the boxes | ||
* First index on vector is a vertex on the left side of the bipartite graph | ||
* and the vector on that index contains indices of vertex on the right side of | ||
* of the graph where an edge exists between them. | ||
*/ | ||
std::vector<std::vector<int16_t>> graph; | ||
|
||
/** | ||
* @brief The amount of vertices in the left side of the bipartite graph | ||
*/ | ||
int16_t leftVerticesCount; | ||
|
||
/** | ||
* @brief The amount of vertices in the left side of the bipartite graph | ||
*/ | ||
int16_t rightVerticesCount; | ||
|
||
/** | ||
* @brief The index of the NILL node in the left part of the bipartite graph | ||
*/ | ||
int16_t NILL; // NOLINT | ||
|
||
/** | ||
* @brief Used as marker for infinite distance | ||
*/ | ||
int16_t INFINITE = std::numeric_limits<int16_t>::max(); // NOLINT | ||
|
||
/** | ||
* @brief Contains whether vertices on the left side of the bipartite graph are | ||
* currently part of a match. Where the index is the vertex index and the | ||
* the value is the index of the vertex in the right side of the graph that | ||
* is matched to it. -1 indicates no match | ||
*/ | ||
mutable std::vector<int16_t> pairsLeft; | ||
|
||
/** | ||
* @brief Contains whether vertices on the right side of the bipartite graph are | ||
* currently part of a match. Where the index is the vertex index and the | ||
* the value is the index of the vertex in the left side of the graph that | ||
* is matched to it. -1 indicates no match | ||
*/ | ||
mutable std::vector<int16_t> pairsRight; | ||
|
||
/** | ||
* @brief Stores distances of left vertices | ||
*/ | ||
mutable std::vector<int16_t> distances; | ||
}; | ||
|
||
} // namespace BoxNesting |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.