Skip to content
This repository has been archived by the owner on Apr 17, 2024. It is now read-only.

Commit

Permalink
Project Verification
Browse files Browse the repository at this point in the history
Complete verification of all projects
  • Loading branch information
Alexandre Hallaine committed Nov 5, 2023
1 parent c2d0412 commit 7d3cb1d
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 393 deletions.
36 changes: 19 additions & 17 deletions include/Heuristic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@

#include <vector>

class Heuristic {
public:
virtual ~Heuristic() = default;
namespace NPuzzle {
class Heuristic {
public:
virtual ~Heuristic() = default;

virtual int calculate(const std::vector<int> &board, int size) = 0;
};
virtual int calculate(const std::vector<int> &board, int size) = 0;
};

class MisplacedTiles : public Heuristic {
public:
[[nodiscard]] int calculate(const std::vector<int> &board, int size) override;
};
class Heuristic_MisplacedTiles : public Heuristic {
public:
[[nodiscard]] int calculate(const std::vector<int> &board, int size) override;
};

class ManhattanDistance : public Heuristic {
public:
[[nodiscard]] int calculate(const std::vector<int> &board, int size) override;
};
class Heuristic_ManhattanDistance : public Heuristic {
public:
[[nodiscard]] int calculate(const std::vector<int> &board, int size) override;
};

class LinearConflict : public ManhattanDistance {
public:
[[nodiscard]] int calculate(const std::vector<int> &board, int size) override;
};
class Heuristic_LinearConflict : public Heuristic_ManhattanDistance {
public:
[[nodiscard]] int calculate(const std::vector<int> &board, int size) override;
};
}
91 changes: 45 additions & 46 deletions include/Node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,48 @@

#include <memory>

class Node {
template<typename T> friend
class Search;

private:
const std::vector<int> board;
const std::shared_ptr<Node> parent;
const std::shared_ptr<Heuristic> heuristic;

int cost_value = 0;
int heuristic_value = 0;
int size;

Node(const std::vector<int> &board, int size, const std::shared_ptr<Heuristic> &heuristic,
const std::shared_ptr<Node> &parent);

Node(const Puzzle &puzzle, const std::shared_ptr<Heuristic> &heuristic);

public:

[[nodiscard]] const std::shared_ptr<Node> &getParent() const;
[[nodiscard]] const std::vector<int> &getBoard() const;
[[nodiscard]] std::vector<std::shared_ptr<Node>> getSuccessors() const;

[[nodiscard]] int getCost() const;
[[nodiscard]] int getHeuristic() const;
[[nodiscard]] int getScore() const;

[[nodiscard]] Puzzle getPuzzle() const;
};

struct NodeComparator {
virtual bool operator()(const std::shared_ptr<Node> &lhs, const std::shared_ptr<Node> &rhs) const = 0;
};

struct AStarComparator : public NodeComparator {
[[nodiscard]] bool operator()(const std::shared_ptr<Node> &lhs, const std::shared_ptr<Node> &rhs) const override;
};

struct GreedyComparator : public NodeComparator {
[[nodiscard]] bool operator()(const std::shared_ptr<Node> &lhs, const std::shared_ptr<Node> &rhs) const override;
};

struct UniformCostComparator : public NodeComparator {
[[nodiscard]] bool operator()(const std::shared_ptr<Node> &lhs, const std::shared_ptr<Node> &rhs) const override;
};
namespace NPuzzle {
class Node {
private:
std::shared_ptr<Heuristic> heuristic = nullptr;
const std::shared_ptr<Node> parent = nullptr;
const std::vector<int> board;
int size = 0;

int cost_value = 0;
int heuristic_value = 0;

public:
Node(const Puzzle &puzzle, const std::shared_ptr<Heuristic> &heuristic);
Node(std::vector<int> board, std::shared_ptr<Node> parent);

[[nodiscard]] int getCost() const;
[[nodiscard]] int getHeuristic() const;
[[nodiscard]] int getScore() const;

[[nodiscard]] const std::shared_ptr<Node> &getParent() const;
[[nodiscard]] const std::vector<int> &getBoard() const;
[[nodiscard]] Puzzle getPuzzle() const;

void getSuccessors(std::shared_ptr<Node> &me, std::vector<std::shared_ptr<Node>> &successors) const;
};

struct NodeComparator {
virtual bool operator()(const std::shared_ptr<Node> &lhs, const std::shared_ptr<Node> &rhs) const = 0;
};

struct NodeComparator_AStar : public NodeComparator {
[[nodiscard]] bool
operator()(const std::shared_ptr<Node> &lhs, const std::shared_ptr<Node> &rhs) const override;
};

struct NodeComparator_Greedy : public NodeComparator {
[[nodiscard]] bool
operator()(const std::shared_ptr<Node> &lhs, const std::shared_ptr<Node> &rhs) const override;
};

struct NodeComparator_UniformCost : public NodeComparator {
[[nodiscard]] bool
operator()(const std::shared_ptr<Node> &lhs, const std::shared_ptr<Node> &rhs) const override;
};
}
29 changes: 14 additions & 15 deletions include/Puzzle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,22 @@
#include <vector>
#include <ostream>

class Puzzle {
friend class Node;
namespace NPuzzle {
class Puzzle {
friend class Node;

private:
std::vector<int> board;
int size;
private:
std::vector<int> board;
int size = 0;

[[nodiscard]] bool isSolvable() const;
explicit Puzzle(const std::vector<int> &board);

explicit Puzzle(const std::vector<int> &board);
[[nodiscard]] bool isSolvable() const;

public:
explicit Puzzle(int size = 3);
explicit Puzzle(const std::string &filename);
public:
explicit Puzzle(int size = 3);
explicit Puzzle(const std::string &filename);

[[nodiscard]] std::vector<int> getBoard() const;

friend std::ostream &operator<<(std::ostream &os, const Puzzle &puzzle);

};
friend std::ostream &operator<<(std::ostream &os, const Puzzle &puzzle);
};
}
78 changes: 39 additions & 39 deletions include/Search.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,50 @@
#include <unordered_set>
#include <stack>

class SearchBase {
public:
virtual ~SearchBase() = default;

virtual std::unique_ptr<std::stack<Puzzle>> solve(const Puzzle &puzzle) = 0;
virtual void printStats() = 0;
};

template<typename NodeComparator = AStarComparator>
class Search : public SearchBase {
private:
struct VectorHash {
size_t operator()(const std::vector<int> &v) const {
std::hash<int> hasher;
size_t seed = 0;
for (int i: v) {
// Combine the hash of the current element with the
// running total using a bitwise XOR and bit shifting to
// reduce the chance of collisions.
seed ^= hasher(i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
namespace NPuzzle {
class SearchBase {
public:
virtual ~SearchBase() = default;

virtual std::unique_ptr<std::stack<Puzzle>>
solve(const Puzzle &puzzle, const std::shared_ptr<Heuristic> &heuristic) = 0;
virtual void printStats() = 0;
};

std::priority_queue<std::shared_ptr<Node>, std::vector<std::shared_ptr<Node>>, NodeComparator> frontier;
std::unordered_set<std::vector<int>, VectorHash> visited;

std::shared_ptr<Heuristic> heuristic;
template<typename NodeComparator = NodeComparator_AStar>
class Search : public SearchBase {
private:
struct VectorHash {
size_t operator()(const std::vector<int> &v) const {
std::hash<int> hasher;
size_t seed = 0;
for (int i: v) {
// Combine the hash of the current element with the
// running total using a bitwise XOR and bit shifting to
// reduce the chance of collisions.
seed ^= hasher(i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
};

std::stack<Puzzle> reconstructPath(const std::shared_ptr<Node> &node);
std::priority_queue<std::shared_ptr<Node>, std::vector<std::shared_ptr<Node>>, NodeComparator> frontier;
std::unordered_set<std::vector<int>, VectorHash> visited;

public:
explicit Search(const std::shared_ptr<Heuristic> &heuristic);
std::stack<Puzzle> reconstructPath(const std::shared_ptr<Node> &node);

[[nodiscard]] std::unique_ptr<std::stack<Puzzle>> solve(const Puzzle &puzzle) override;
void printStats() override;
};
public:
[[nodiscard]] std::unique_ptr<std::stack<Puzzle>>
solve(const Puzzle &puzzle, const std::shared_ptr<Heuristic> &heuristic) override;
void printStats() override;
};

template
class Search<AStarComparator>;
template
class Search<NodeComparator_AStar>;

template
class Search<GreedyComparator>;
template
class Search<NodeComparator_Greedy>;

template
class Search<UniformCostComparator>;
template
class Search<NodeComparator_UniformCost>;
}
93 changes: 42 additions & 51 deletions src/Heuristic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,52 @@

#include <cmath>

int MisplacedTiles::calculate(const std::vector<int> &board, int size) {
(void) size;

int misplacedTiles = 0;
for (int i = 0; i < (int) board.size(); i++)
if (board[i] != 0 && board[i] != i + 1)
misplacedTiles++;

return misplacedTiles;
}

int ManhattanDistance::calculate(const std::vector<int> &board, int size) {
int manhattanDistance = 0;
for (int i = 0; i < (int) board.size(); i++) {
int value = board[i];
if (value != 0) {
int x = i % size;
int y = i / size;
int goalX = (value - 1) % size;
int goalY = (value - 1) / size;
manhattanDistance += std::abs(x - goalX) + std::abs(y - goalY);
}
namespace NPuzzle {
int Heuristic_MisplacedTiles::calculate(const std::vector<int> &board, int /* size */) {
int misplacedTiles = 0;
for (size_t i = 0, len = board.size(); i < len; ++i)
misplacedTiles += board[i] != 0 && board[i] != static_cast<int>(i) + 1;
return misplacedTiles;
}

return manhattanDistance;
}

int LinearConflict::calculate(const std::vector<int> &board, int size) {
int linearConflict = 0;
for (int i = 0; i < size; ++i) // For each row and column
{
for (int j = 0; j < size - 1; ++j) // For each pair in the row/column
{
int value_row = board[i * size + j];
int value_col = board[j * size + i];
for (int k = j + 1; k < size; ++k) // Compare with subsequent tiles
{
int other_value_row = board[i * size + k];
int other_value_col = board[k * size + i];

// Check if value_row is in its goal row and there is a tile that should come after it
if (value_row != 0 && (value_row - 1) / size == i && other_value_row != 0 &&
(other_value_row - 1) / size == i && value_row > other_value_row) {
linearConflict++;
}
int Heuristic_ManhattanDistance::calculate(const std::vector<int> &board, int size) {
int manhattanDistance = 0;
for (size_t i = 0, len = board.size(); i < len; ++i)
if (board[i] != 0) {
int tile = board[i] - 1;
manhattanDistance += std::abs(static_cast<int>(tile % size) - static_cast<int>(i % size)) +
std::abs(static_cast<int>(tile / size) - static_cast<int>(i / size));
}
return manhattanDistance;
}

// Check if value_col is in its goal column and there is a tile that should come after it
if (value_col != 0 && (value_col - 1) % size == i && other_value_col != 0 &&
(other_value_col - 1) % size == i && value_col > other_value_col) {
linearConflict++;
int Heuristic_LinearConflict::calculate(const std::vector<int> &board, int size) {
int linearConflict = 0;
int manhattanDistance = Heuristic_ManhattanDistance::calculate(board, size);

for (int row = 0; row < size; ++row)
for (int col = 0; col < size; ++col) {
int index = row * size + col;
int tile = board[index];
if (tile != 0) {
int goalRow = (tile - 1) / size;
int goalCol = (tile - 1) % size;

if (goalRow == row)
for (int k = col + 1; k < size; ++k) {
int otherTile = board[row * size + k];
if (otherTile != 0 && (otherTile - 1) / size == row && tile > otherTile)
linearConflict++;
}
if (goalCol == col)
for (int k = row + 1; k < size; ++k) {
int otherTile = board[k * size + col];
if (otherTile != 0 && (otherTile - 1) % size == col && tile > otherTile)
linearConflict++;
}
}
}
}
}

// Each conflict accounts for 2 additional moves
return ManhattanDistance::calculate(board, size) + 2 * linearConflict;
return manhattanDistance + 2 * linearConflict;
}
}
Loading

0 comments on commit 7d3cb1d

Please sign in to comment.