Advertisement
Litigare

Untitled

Jun 16th, 2021
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.91 KB | None | 0 0
  1. #include "AStar.h"
  2. #include <algorithm>
  3. #include <iostream>
  4. #include "mpi.h"
  5. #include "Coordinate.h"
  6. #include "Node.h"
  7. #include "Heuristic.h"
  8. #include "AStarMPICommunication.h"
  9.  
  10. #define RESULT_TAG 1
  11. #define TASK_TAG 2
  12.  
  13. using namespace std::placeholders;
  14.  
  15.  
  16. struct Para {//pomocnicza struktura do przechowania wynikow
  17.     NodeSet n;
  18.     int G;
  19.     void setNode(NodeSet nod) {
  20.         this->n = nod;
  21.     }
  22. };
  23.  
  24.  
  25.  
  26. AStar::AStar()
  27. {
  28.     setDiagonalMovement(false);
  29.     setHeuristic(&Heuristic::euclidean);
  30.  
  31.     wallSymbol = '0';
  32.     freeSymbol = '-';
  33.     pathSymbol = 'X';
  34.     startSymbol = 'S';
  35.     endSymbol = 'E';
  36.  
  37.     direction = {
  38.         { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 },
  39.         { -1, -1 }, { 1, 1 }, { -1, 1 }, { 1, -1 }
  40.     };
  41. }
  42.  
  43. void AStar::setMapSize(Coordinate worldSize_)
  44. {
  45.     worldSize = worldSize_;
  46. }
  47.  
  48. void AStar::setDiagonalMovement(bool enable_)
  49. {
  50.     directions = (enable_ ? 8 : 4);
  51. }
  52.  
  53. void AStar::setHeuristic(HeuristicFunction heuristic_)
  54. {
  55.     heuristic = std::bind(heuristic_, _1, _2);
  56. }
  57.  
  58. void AStar::addCollision(Coordinate coordinates_)
  59. {
  60.     walls.push_back(coordinates_);
  61. }
  62.  
  63. void AStar::removeCollision(Coordinate coordinates_)
  64. {
  65.     auto it = std::find(walls.begin(), walls.end(), coordinates_);
  66.  
  67.     if (it != walls.end()) {
  68.         walls.erase(it);
  69.     }
  70. }
  71.  
  72. void AStar::clearCollisions()
  73. {
  74.     walls.clear();
  75. }
  76.  
  77. void AStar::updateMap()//aktualizacja mapy
  78. {
  79.     map = new char*[worldSize.x];
  80.  
  81.     for (int x = 0; x < worldSize.x; ++x)
  82.     {
  83.         map[x] = new char[worldSize.y];
  84.     }
  85.  
  86.     for (auto x = 0; x < worldSize.x; x++)
  87.     {
  88.         for (auto y = 0; y < worldSize.y; y++)
  89.         {
  90.             map[x][y] = freeSymbol;
  91.         }
  92.     }
  93.  
  94.     for (auto wall : walls)
  95.     {
  96.         map[wall.x][wall.y] = wallSymbol;
  97.     }
  98.  
  99.     if (start == end) {
  100.         return;
  101.     }
  102.  
  103.     map[start.x][start.y] = startSymbol;
  104.     map[end.x][end.y] = endSymbol;
  105. }
  106.  
  107. void AStar::updateMap(CoordinateList path_)
  108. {
  109.     updateMap();
  110.  
  111.     for (auto& coordinate : path_) {
  112.         if (coordinate == start || coordinate == end) {
  113.             continue;
  114.         }
  115.  
  116.         map[coordinate.x][coordinate.y] = pathSymbol;
  117.     }
  118. }
  119.  
  120. void AStar::showMap() //wyswietlenie mapy
  121. {
  122.     for (auto y = 0; y < worldSize.y; y++)
  123.     {
  124.         for (auto x = 0; x < worldSize.x; x++)
  125.         {
  126.             std::cout << map[x][y] << " ";
  127.         }
  128.  
  129.         std::cout << "\n";
  130.     }
  131. }
  132.  
  133. CoordinateList AStar::findPath(Coordinate start_, Coordinate end_)
  134. {
  135.     start = start_;
  136.     end = end_;
  137.  
  138.     Node *currentNode = nullptr;
  139.     NodeSet openSet, closedSet;
  140.  
  141.     openSet.reserve(300);
  142.     closedSet.reserve(300);
  143.  
  144.     openSet.push_back(new Node(start_));
  145.  
  146.     while (!openSet.empty()) {
  147.         auto currentNodeIteartor = openSet.begin();
  148.         currentNode = *currentNodeIteartor;
  149.  
  150.         for (auto iterator = openSet.begin(); iterator != openSet.end(); iterator++) {
  151.             auto node = *iterator;
  152.             if (node->getScore() <= currentNode->getScore()) {
  153.                 currentNode = node;
  154.                 currentNodeIteartor = iterator;
  155.             }
  156.         }
  157.  
  158.         if (currentNode->coordinates == end_) {
  159.             break;
  160.         }
  161.  
  162.         //MPI_Bcast(&current, 1, MPI_INT, 0, MPI_COMM_WORLD);
  163.  
  164.         closedSet.push_back(currentNode);
  165.         openSet.erase(currentNodeIteartor);
  166.  
  167.         for (int i = 0; i < directions; ++i) {
  168.             Coordinate newCoordinates(currentNode->coordinates + direction[i]);
  169.  
  170.             //SendCoordinateToItsHandlingProcess(newCoordinates);
  171.            
  172.             if (detectCollision(newCoordinates) ||
  173.                 findNodeOnList(closedSet, newCoordinates)) {
  174.                 continue;
  175.             }
  176.  
  177.             int totalCost = currentNode->G + ((i < 4) ? 10 : 14);
  178.  
  179.             Node *successor = findNodeOnList(openSet, newCoordinates);
  180.             if (successor == nullptr) {
  181.                 successor = new Node(newCoordinates, currentNode);
  182.                 successor->G = totalCost;
  183.                 successor->H = heuristic(successor->coordinates, end_);
  184.                 openSet.push_back(successor);
  185.             }
  186.             else if (totalCost < successor->G) {
  187.                 successor->parent = currentNode;
  188.                 successor->G = totalCost;
  189.             }
  190.         }
  191.     }
  192.  
  193.     CoordinateList path;
  194.     while (currentNode != nullptr) {
  195.         path.push_back(currentNode->coordinates);
  196.         currentNode = currentNode->parent;
  197.     }
  198.  
  199.     releaseNodes(openSet);
  200.     releaseNodes(closedSet);
  201.  
  202.     return path;
  203. }
  204.  
  205. CoordinateList AStar::findPathMPI(Coordinate start_, Coordinate end_, AStarMPICommunication communication, int rank, int size)
  206. {
  207.     if (rank == 0) {
  208.         coordinate(start_, end_, communication, rank, size);
  209.     }
  210.     else {
  211.         performComputations(rank);
  212.     }
  213. }
  214.  
  215. CoordinateList AStar::coordinate(Coordinate start_, Coordinate end_, AStarMPICommunication communication, int rank, int size) {//fcja koordynatora
  216.     start = start_;//start
  217.     end = end_;//i koniec
  218.  
  219.     Node* currentNode = nullptr;//wskaznik na aktualny wierzcholek
  220.     NodeSet openSet, closedSet;//"listy" open i close
  221.  
  222.     openSet.reserve(300);//rezerwacja pamieci
  223.     closedSet.reserve(300);
  224.  
  225.     openSet.push_back(new Node(start_));//umieszcza na liście otwartej wierzcholek startowy
  226.  
  227.     while (!openSet.empty()) {//działa do momentu aż w liście otwartej coś jest
  228.         auto currentNodeIteartor = openSet.begin();//iterator do przechodzenia po wierzcholkach - ustawiamy na poczatek listy
  229.         currentNode = *currentNodeIteartor;//aktualna pozycja najlepszej ścieżki
  230.  
  231.  
  232.  
  233.         std::vector<int> proc_to_task_id(size, -1);//ktory proces dostal zadanie
  234.         //std::vector<int> results(openSet.size());//tu ma byc rozmiar tablicy open
  235.         std::vector<Para> pary(openSet.size());//tablica z aktualnie sprawdzanymi węzłami
  236.         const auto par_start_time = MPI_Wtime();
  237.         int task_id = 0;
  238.  
  239.        
  240.         for (auto iterator = openSet.begin(); iterator != openSet.end(); iterator++) {
  241.             Para p;
  242.             p.G = INT_MAX;
  243.             p.setNode(iterator);//tutaj przydałoby się przypisać node-a
  244.             pary.push_back(p);
  245.         }
  246.  
  247.  
  248.         /*napisać od 0 przydzielanie zadań procesom : proces master przydziela procesom slave zadanie obliczenia kosztu dojścia do wszystkich node - ów
  249.         sąsiadujących z tym, w którym się znajdujemy, procesy zwracają wartości funkcji liczącej koszt dojścia, następnie proces master wybiera z listy
  250.         zwróconych wartości najmniejszą i potem dodaje do listy kolejne wierzchołki sąsiadujące z tym poprzednim i pętla leci od nowa
  251.         po przejściu pętli while funkcja działa dalej*/
  252.  
  253.  
  254.  
  255.         //znalezienie kolejnego wierzcholka
  256.         for (auto iterator = openSet.begin(); iterator != openSet.end(); iterator++) {//przechodzimy przez liste otwarta
  257.             MPI_Status status;
  258.             int result;
  259.             const int code = MPI_Recv(&result, 1, MPI_INT, MPI_ANY_SOURCE, RESULT_TAG, MPI_COMM_WORLD, &status);
  260.             if (code != MPI_SUCCESS) {
  261.                 MPI_Abort(MPI_COMM_WORLD, code);
  262.             }
  263.             //jeśli proces miał przydzielone zadanie to zapisujemy jego wynik
  264.             const auto sender = status.MPI_SOURCE;
  265.             const auto prev_task_id = proc_to_task_id[sender];
  266.             if (prev_task_id != -1) {
  267.                 results[prev_task_id] = result;
  268.             }
  269.  
  270.             //wysyłamy kolejne zadanie
  271.             auto node = *iterator;//aktualna pozycja - wierzcholek
  272.             proc_to_task_id[sender] = task_id;
  273.             MPI_Send(&node->coordinates.x, 1, MPI_INT, sender, TASK_TAG, MPI_COMM_WORLD);//przeslanie danych do wykonania zadania
  274.             MPI_Send(&node->coordinates.y, 1, MPI_INT, sender, TASK_TAG, MPI_COMM_WORLD);//przeslanie danych do wykonania zadania
  275.             MPI_Send(&node->G, 1, MPI_INT, sender, TASK_TAG, MPI_COMM_WORLD);//przeslanie danych do wykonania zadania
  276.             MPI_Send(&node->H, 1, MPI_INT, sender, TASK_TAG, MPI_COMM_WORLD);//przeslanie danych do wykonania zadania
  277.             MPI_Send(&node->parent->coordinates.x, 1, MPI_INT, sender, TASK_TAG, MPI_COMM_WORLD);//przeslanie danych do wykonania zadania
  278.             MPI_Send(&node->parent->coordinates.y, 1, MPI_INT, sender, TASK_TAG, MPI_COMM_WORLD);//przeslanie danych do wykonania zadania
  279.             //MPI_Send(&node, 1, MPI_PACKED, sender, TASK_TAG, MPI_COMM_WORLD);//przeslanie danych do wykonania zadania
  280.  
  281.             ++task_id;
  282.  
  283.             //sprawdzenie który wynik najmniejszy
  284.  
  285.             /*if (node->getScore() <= currentNode->getScore()) {//jesli całkowity koszt dla danego jest mniejszy lub rowny niż do globalnego
  286.                 currentNode = node;//to ustaw go jako globalny
  287.                 currentNodeIteartor = iterator;
  288.             }*/
  289.         }
  290.  
  291.         if (currentNode->coordinates == end_) {//jesli dotarlismy do ostatniego to wyjdz z pętli
  292.             break;
  293.         }
  294.  
  295.         closedSet.push_back(currentNode);//dodaj odwiedzony do listy zamknietej
  296.         openSet.erase(currentNodeIteartor);//usun odwiedzony z listy otwartej
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.         //znalezienie nastepnikow wybranego wierzcholka
  304.         for (int i = 0; i < directions; ++i) {//dodanie do listy kolejnych wierzcholkow następnikow wybranego
  305.             Coordinate newCoordinates(currentNode->coordinates + direction[i]);
  306.  
  307.             //SendCoordinateToItsHandlingProcess(newCoordinates);
  308.  
  309.             if (detectCollision(newCoordinates) || findNodeOnList(closedSet, newCoordinates)) {//jesli kolizja lub wierzcholek już jest na liście to pomiń
  310.                 continue;
  311.             }
  312.  
  313.             int totalCost = currentNode->G + ((i < 4) ? 10 : 14);//podlicz całkowity koszt dojścia
  314.  
  315.             Node* successor = findNodeOnList(openSet, newCoordinates);
  316.             if (successor == nullptr) {
  317.                 successor = new Node(newCoordinates, currentNode);
  318.                 successor->G = totalCost;
  319.                 successor->H = heuristic(successor->coordinates, end_);
  320.                 openSet.push_back(successor);
  321.             }
  322.             else if (totalCost < successor->G) {
  323.                 successor->parent = currentNode;
  324.                 successor->G = totalCost;
  325.             }
  326.         }
  327.     }
  328.  
  329.     CoordinateList path;
  330.     while (currentNode != nullptr) {
  331.         path.push_back(currentNode->coordinates);
  332.         currentNode = currentNode->parent;
  333.     }
  334.  
  335.     releaseNodes(openSet);
  336.     releaseNodes(closedSet);
  337.  
  338.     return path;
  339. }
  340.  
  341. void performComputations(int myrank) {//funkcja slave-a
  342.     const int master = 0;
  343.     int result = -1;
  344.  
  345.     while (true) {
  346.         std::cout << myrank << " przesyła wynik " << result << " do master-a" << std::endl;
  347.         MPI_Send(&result, 1, MPI_INT, master, RESULT_TAG, MPI_COMM_WORLD);
  348.  
  349.         int a, b, c, d, e, f;//zmienne do przechowania tymczasowych wartosci
  350.         Node n;//obiekt do działań - wierzcholek na ktorym wykonuje obliczenia
  351.         MPI_Status status;
  352.         MPI_Recv(&a, 1, MPI_INT, master, TASK_TAG, MPI_COMM_WORLD, &status);
  353.         MPI_Recv(&b, 1, MPI_INT, master, TASK_TAG, MPI_COMM_WORLD, &status);
  354.         MPI_Recv(&c, 1, MPI_INT, master, TASK_TAG, MPI_COMM_WORLD, &status);
  355.         MPI_Recv(&d, 1, MPI_INT, master, TASK_TAG, MPI_COMM_WORLD, &status);
  356.         MPI_Recv(&e, 1, MPI_INT, master, TASK_TAG, MPI_COMM_WORLD, &status);
  357.         MPI_Recv(&f, 1, MPI_INT, master, TASK_TAG, MPI_COMM_WORLD, &status);
  358.         //MPI_Recv(&n, 1, MPI_PACKED, master, TASK_TAG, MPI_COMM_WORLD, &status);
  359.         n.coordinates.x = a;
  360.         n.coordinates.y = b;
  361.         n.G = c;
  362.         n.H = d;
  363.         n.parent->coordinates.x = e;
  364.         n.parent->coordinates.y = f;
  365.         if (is_empty_task(a) || is_empty_task(b) || is_empty_task(c) || is_empty_task(d) || is_empty_task(e) || is_empty_task(f))break;
  366.  
  367.  
  368.         std::cout << myrank << " otrzymał node: [" << n.coordinates.x << " | " << n.coordinates.y << "] od mastera" << std::endl;
  369.  
  370.         result = n.getScore();
  371.     }
  372. }
  373. int empty_task() {
  374.     return -1;
  375. }
  376. bool is_empty_task(int task) {
  377.     return -1 == task;
  378. }
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414. Node* AStar::findNodeOnList(NodeSet& nodes_, Coordinate coordinates_)
  415. {
  416.     for (auto node : nodes_) {
  417.         if (node->coordinates == coordinates_) {
  418.             return node;
  419.         }
  420.     }
  421.  
  422.     return nullptr;
  423. }
  424.  
  425. void AStar::releaseNodes(NodeSet& nodes_)
  426. {
  427.     for (auto it = nodes_.begin(); it != nodes_.end();) {
  428.         delete *it;
  429.         it = nodes_.erase(it);
  430.     }
  431. }
  432.  
  433. bool AStar::detectCollision(Coordinate coordinates_)
  434. {
  435.     if (coordinates_.x < 0 || coordinates_.x >= worldSize.x ||
  436.         coordinates_.y < 0 || coordinates_.y >= worldSize.y ||
  437.         std::find(walls.begin(), walls.end(), coordinates_) != walls.end()
  438.     ) {
  439.         return true;
  440.     }
  441.  
  442.     return false;
  443. }
  444.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement