Skip to content

Commit

Permalink
Merge pull request #42 from UmbrellaLeaf5/FindOptimalWay
Browse files Browse the repository at this point in the history
Find optimal way
  • Loading branch information
UmbrellaLeaf5 authored Apr 15, 2024
2 parents b70066b + cd3eed8 commit 7ae91f4
Show file tree
Hide file tree
Showing 15 changed files with 1,198 additions and 1 deletion.
151 changes: 151 additions & 0 deletions backend/adjacency_matrix.cpp
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]);
}
95 changes: 95 additions & 0 deletions backend/adjacency_matrix.h
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;
};
99 changes: 99 additions & 0 deletions backend/optimal_way/circle_obstacle.h
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
Loading

0 comments on commit 7ae91f4

Please sign in to comment.