-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #42 from UmbrellaLeaf5/FindOptimalWay
Find optimal way
- Loading branch information
Showing
15 changed files
with
1,198 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
#include "adjacency_matrix.h" | ||
|
||
#include <cfloat> | ||
|
||
AdjacencyMatrix::AdjacencyMatrix(std::vector<std::vector<double>> nums, | ||
bool is_minor) | ||
: matrix_{nums}, | ||
size_{nums.size() - is_minor}, | ||
min_numbers_(size_ + size_) { | ||
if (!is_minor) { | ||
matrix_.resize(size_ + 1); | ||
matrix_[size_].resize(size_ + 1); | ||
for (std::size_t i = 0; i < size_; ++i) { | ||
matrix_[i].resize(size_ + 1); | ||
matrix_[i][size_] = i; | ||
matrix_[size_][i] = i; | ||
} | ||
} | ||
CalculateData(); | ||
} | ||
|
||
AdjacencyMatrix& AdjacencyMatrix::operator=(const AdjacencyMatrix& m) { | ||
size_ = m.size_; | ||
matrix_ = m.matrix_; | ||
reducted_matrix_ = m.reducted_matrix_; | ||
min_numbers_ = m.min_numbers_; | ||
evaluation_ = m.evaluation_; | ||
selected_value_ = m.selected_value_; | ||
selected_edge_ = m.selected_edge_; | ||
return *this; | ||
} | ||
|
||
void AdjacencyMatrix::SetMatrixValue(std::size_t i, std::size_t j, double num) { | ||
matrix_[i][j] = num; | ||
CalculateData(); | ||
} | ||
|
||
AdjacencyMatrix AdjacencyMatrix::Minor(std::size_t i, std::size_t j) { | ||
std::vector<std::vector<double>> minor_matrix = matrix_; | ||
minor_matrix.erase(minor_matrix.begin() + i); | ||
for (std::size_t k = 0; k < size_ + 1; ++k) { | ||
minor_matrix[k].erase(minor_matrix[k].begin() + j); | ||
} | ||
AdjacencyMatrix minor(minor_matrix, true); | ||
minor.CalculateData(); | ||
return minor; | ||
} | ||
|
||
AdjacencyMatrix AdjacencyMatrix::Reducted() { | ||
AdjacencyMatrix reducted = *this; | ||
reducted.matrix_ = reducted_matrix_; | ||
return reducted; | ||
} | ||
|
||
Minimums AdjacencyMatrix::FindTwoMinimums(Mins type, std::size_t index) const { | ||
Minimums result; | ||
double first_min = FLT_MAX; | ||
double second_min = FLT_MAX; | ||
switch (type) { | ||
case Mins::Rows: { | ||
for (std::size_t j = 0; j < size_; ++j) { | ||
if (reducted_matrix_[index][j] < first_min) { | ||
second_min = first_min; | ||
first_min = reducted_matrix_[index][j]; | ||
} else if (reducted_matrix_[index][j] < second_min) { | ||
second_min = reducted_matrix_[index][j]; | ||
} | ||
} | ||
result.first = first_min; | ||
result.second = second_min; | ||
break; | ||
} | ||
|
||
case Mins::Columns: { | ||
for (std::size_t i = 0; i < size_; ++i) { | ||
if (reducted_matrix_[i][index] < first_min) { | ||
second_min = first_min; | ||
first_min = reducted_matrix_[i][index]; | ||
} else if (reducted_matrix_[i][index] < second_min) { | ||
second_min = reducted_matrix_[i][index]; | ||
} | ||
} | ||
result.first = first_min; | ||
result.second = second_min; | ||
break; | ||
} | ||
|
||
default: { | ||
result.first = first_min; | ||
result.second = second_min; | ||
break; | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
double AdjacencyMatrix::BottomLineEvaluation() { | ||
reducted_matrix_ = matrix_; | ||
double mins_sum = 0; | ||
for (std::size_t i = 0; i < size_; ++i) { | ||
Minimums twoMins = FindTwoMinimums(Mins::Rows, i); | ||
double first_min = twoMins.first; | ||
double second_min = twoMins.second; | ||
for (std::size_t j = 0; j < size_; ++j) { | ||
reducted_matrix_[i][j] -= first_min; | ||
} | ||
second_min -= first_min; | ||
min_numbers_[i] = second_min; | ||
mins_sum += first_min; | ||
} | ||
|
||
for (std::size_t i = 0; i < size_; ++i) { | ||
Minimums twoMins = FindTwoMinimums(Mins::Columns, i); | ||
double first_min = twoMins.first; | ||
double second_min = twoMins.second; | ||
for (std::size_t j = 0; j < size_; ++j) { | ||
if (reducted_matrix_[j][i] == min_numbers_[j]) | ||
min_numbers_[j] -= first_min; | ||
reducted_matrix_[j][i] -= first_min; | ||
} | ||
second_min -= first_min; | ||
min_numbers_[size_ + i] = second_min; | ||
mins_sum += first_min; | ||
} | ||
|
||
return mins_sum; | ||
} | ||
|
||
std::pair<std::size_t, std::size_t> AdjacencyMatrix::HighestPowerOfZero() const { | ||
std::size_t row = 0, col = 0; | ||
double max = 0; | ||
for (std::size_t i = 0; i < size_; ++i) { | ||
for (std::size_t j = 0; j < size_; ++j) { | ||
if (reducted_matrix_[i][j] == 0) { | ||
if ((min_numbers_[i] + min_numbers_[size_ + j]) > max) { | ||
max = min_numbers_[i] + min_numbers_[size_ + j]; | ||
row = i; | ||
col = j; | ||
} | ||
} | ||
} | ||
} | ||
return std::make_pair(row, col); | ||
} | ||
|
||
void AdjacencyMatrix::CalculateData() { | ||
evaluation_ = BottomLineEvaluation(); | ||
selected_value_ = HighestPowerOfZero(); | ||
selected_edge_ = std::make_pair(matrix_[selected_value_.first][size_], | ||
matrix_[size_][selected_value_.second]); | ||
} |
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,95 @@ | ||
#pragma once | ||
|
||
#include <vector> | ||
|
||
// Структура для хранения двух минимумов строки/столбца | ||
struct Minimums { | ||
double first; | ||
double second; | ||
}; | ||
|
||
class AdjacencyMatrix { | ||
public: | ||
AdjacencyMatrix(std::size_t size) : size_{size}, min_numbers_(size_ + size_) { | ||
matrix_.resize(size_ + 1); | ||
for (auto& elem : matrix_) { | ||
elem.resize(size_ + 1, 0.0); | ||
} | ||
for (std::size_t i = 0; i < size_; ++i) { | ||
matrix_[i][size_] = i; | ||
matrix_[size_][i] = i; | ||
} | ||
min_numbers_.resize(size_ + size_); | ||
} | ||
|
||
// Конструктор по вектору векторов | ||
// Зависит от того, является ли полученная матрица минором | ||
AdjacencyMatrix(std::vector<std::vector<double>> nums, bool is_minor = false); | ||
|
||
enum Mins { Rows, Columns }; | ||
|
||
// Копирующее присваивание для матрицы | ||
AdjacencyMatrix& operator=(const AdjacencyMatrix& m); | ||
|
||
// Изменение элемента матрицы | ||
void SetMatrixValue(std::size_t i, std::size_t j, double num); | ||
|
||
// Возвращает размер матрицы | ||
std::size_t GetSize() const { return size_; } | ||
|
||
// Возвращает элемент матрицы | ||
double GetMatrixValue(std::size_t i, std::size_t j) const { return matrix_[i][j]; } | ||
|
||
// Возвращает оценку расстояния | ||
double GetBottomLineEvaluation() const { return evaluation_; } | ||
|
||
// Возвращает выбранное на данной итерации | ||
// ребро для последующего рассмотрения | ||
std::pair<std::size_t, std::size_t> GetSelectedEdge() const { return selected_edge_; } | ||
|
||
// Возвращает выбранное на данной итерации | ||
// значение матрицы для последующего рассмотрения | ||
std::pair<std::size_t, std::size_t> GetSelectedValue() const { return selected_value_; } | ||
// Возвращает минор матрицы(без i-той строки и j-того столбца) | ||
AdjacencyMatrix Minor(std::size_t i, std::size_t j); | ||
|
||
// Возвращает редуцированную версию матрицы | ||
AdjacencyMatrix Reducted(); | ||
|
||
// Считает данные для матрицы | ||
void CalculateData(); | ||
|
||
private: | ||
// Размер матрицы | ||
std::size_t size_; | ||
|
||
// Матрица | ||
std::vector<std::vector<double>> matrix_; | ||
|
||
// Редуцированная версия матрицы | ||
std::vector<std::vector<double>> reducted_matrix_; | ||
|
||
// Минимальный элемент в каждой строке и в каждом столбце | ||
std::vector<double> min_numbers_; | ||
|
||
// Оценка пути для данной матрицы | ||
double evaluation_ = 0; | ||
|
||
// Ребро, которое выбирается для следующего шага в алгоритме Литтла | ||
std::pair<std::size_t, std::size_t> selected_edge_; | ||
|
||
// Значение матрицы, которое выбирается для следующего шага в алгоритме | ||
// Литтла | ||
std::pair<std::size_t, std::size_t> selected_value_; | ||
|
||
// Найти 2 минимума в строке или столбце | ||
Minimums FindTwoMinimums(Mins type, std::size_t index) const; | ||
|
||
// Редуцирует матрицу сначала по строкам, затем по столбцам | ||
// Находит нижнюю оценку для матрицы | ||
double BottomLineEvaluation(); | ||
|
||
// Возвращает позицию нуля с наибольшей степенью(сумма минимального элемента | ||
// в этой же строке и в этом же столбце) | ||
std::pair<std::size_t, std::size_t> HighestPowerOfZero() const; | ||
}; |
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,99 @@ | ||
#pragma once | ||
|
||
#include <cmath> | ||
#include <memory> | ||
#include <vector> | ||
|
||
#include "../lib/point.h" | ||
|
||
namespace math { | ||
|
||
constexpr double precision = lib::precision; | ||
|
||
/// @brief прямая вида ax+by+c=0 | ||
struct LinearFunction { | ||
LinearFunction(double a, double b, double c) | ||
: a_coef{a}, b_coef{b}, c_coef{c} {} | ||
|
||
LinearFunction(const lib::Point& point1, const lib::Point& point2) { | ||
a_coef = (point2.y - point1.y) / (point2.x - point1.x); | ||
b_coef = -1; | ||
c_coef = point1.y - a_coef * point1.x; | ||
} | ||
|
||
double a_coef, b_coef, c_coef; | ||
|
||
bool operator==(const LinearFunction& other) { | ||
return (std::abs(a_coef - other.a_coef) < precision && | ||
std::abs(b_coef - other.b_coef) < precision && | ||
std::abs(c_coef - other.c_coef) < precision); | ||
} | ||
}; | ||
|
||
/// @brief точка с геометрическими связями | ||
struct Point : public lib::Point { | ||
Point(double xx, double yy) : lib::Point{xx, yy} {} | ||
|
||
// Касательные, проходящие через точку | ||
std::vector<LinearFunction> tangents; | ||
|
||
// Вторая точка касательной | ||
std::shared_ptr<lib::Point> another_tangent_point = nullptr; | ||
}; | ||
|
||
/// @brief круговое препятствие | ||
class CircleObstacle { | ||
public: | ||
/** | ||
* @brief инициалирует экземпляр CircleObstacle | ||
* @param center: центр круга | ||
* @param radius: радиус круга | ||
*/ | ||
CircleObstacle(Point center, double radius) | ||
: center_{center}, radius_{radius} {} | ||
|
||
CircleObstacle() : center_{0, 0}, radius_{0} {} | ||
|
||
Point GetCenter() const { return center_; } | ||
|
||
double GetRadius() const { return radius_; } | ||
|
||
std::vector<LinearFunction> GetTangentLines() { return tangents_; } | ||
|
||
std::vector<Point> GetTangentPoints() { return tangent_points_; } | ||
|
||
void SetCenter(const Point& center) { center_ = center; } | ||
|
||
void SetRadius(double r) { radius_ = r; } | ||
|
||
void AddTangentLine(const LinearFunction& tangent) { | ||
tangents_.push_back(tangent); | ||
} | ||
|
||
void AddTangentPoint(const Point& tangent_point) { | ||
tangent_points_.push_back(tangent_point); | ||
} | ||
|
||
bool operator==(const CircleObstacle& other) { | ||
return (center_ == other.center_ && | ||
std::abs(radius_ - other.radius_) < precision); | ||
} | ||
|
||
bool operator!=(const CircleObstacle& other) { | ||
return (center_ != other.center_ || | ||
std::abs(radius_ - other.radius_) >= precision); | ||
} | ||
|
||
private: | ||
Point center_; | ||
|
||
double radius_; | ||
|
||
// Касательные | ||
std::vector<LinearFunction> tangents_; | ||
|
||
// Точки касания | ||
std::vector<Point> tangent_points_; | ||
}; | ||
|
||
} // namespace math |
Oops, something went wrong.