Advertisement
dark-s0ul

AI

Nov 9th, 2019 (edited)
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.11 KB | None | 0 0
  1. #include <cmath>
  2. #include <array>
  3. #include <random>
  4. #include <chrono>
  5. #include <iostream>
  6. #include <iomanip>
  7. #include <bit>
  8. #include <cstring>
  9. #include <fstream>
  10. #include <sstream>
  11. #include <optional>
  12.  
  13. namespace lab1 {
  14.     template <typename T, size_t count>
  15.     using Array = std::array<T, count>;
  16.  
  17.     template <typename T, size_t rows, size_t cols>
  18.     using Table = Array<Array<T, cols>, rows>;
  19.  
  20.     std::default_random_engine random_engine(0);
  21.  
  22.     auto random_value() {
  23.         return random_engine();
  24.     }
  25.  
  26.     auto random_double() {
  27.         return random_engine() / double(std::default_random_engine::max());
  28.     }
  29.  
  30.     double g(double x, double sigma, double mu) {
  31.         return std::pow(M_E, -std::pow(x - mu, 2) / (2.0 * sigma * sigma)) / (sigma * std::sqrt(2.0 * M_PI));
  32.     }
  33.  
  34.     template <size_t k>
  35.     size_t roulette_wheel(const Array<double, k>& omegas) {
  36.         double sum = 0;
  37.         for (double omega : omegas) {
  38.             sum += omega;
  39.         }
  40.  
  41.         double r = random_double() * sum;
  42.         double total = 0;
  43.         for (size_t i = 1; i <= omegas.size(); i++) {
  44.             total += omegas[i - 1];
  45.             if (total >= r) {
  46.                 return i;
  47.             }
  48.         }
  49.  
  50.         return omegas.size();
  51.     }
  52.  
  53.     template <typename T, size_t k, size_t n, size_t m>
  54.     struct Archive {
  55.         Table<T, k + m, n> s{0};
  56.         Array<T, k + m> f{0};
  57.         Array<T, k + m> omegas{0};
  58.  
  59.         Array<T, n> randomize_s(double a, double b, size_t ant, double q, double epsilon) {
  60.             Array<T, n> out{};
  61.             for (size_t i = 1; i <= n; i++) {
  62.                 out[i - 1] = double(random_value()) * (b - a) / double(std::default_random_engine::max()) - a;
  63.             }
  64.             return out;
  65.         }
  66.  
  67.         double gauss_random(double mu, double sigma) {
  68.             double w, x1;
  69.             do {
  70.                 x1 = 2.0l * (double)(random_value()) / (std::default_random_engine::max() + 1) - 1;
  71.                 double x2 = 2.0l * (double)(random_value()) / (std::default_random_engine::max() + 1) - 1;
  72.                 w = x1 * x1 + x2 * x2;
  73.             } while (w >= 1.0l);
  74.             return mu + sigma * x1 * std::sqrt(-2.0l * log(w) / w);
  75.         }
  76.  
  77.         Array<T, n> construct_s(double a, double b, size_t ant, double q, double epsilon) {
  78.             Array<T, n> out{};
  79.             size_t gil = roulette_wheel(omegas);
  80.             auto& ai = s[gil - 1];
  81.  
  82.             for (size_t i = 1; i <= n; i++) {
  83.                 double mu = ai[i - 1];
  84.                 double sigma = 0;
  85.  
  86.                 {
  87.                     for (size_t e = 1; e <= k; e++) {
  88.                         if (i == gil) continue;
  89.                         sigma += std::abs(s[e - 1][i - 1] - s[e - 1][i - 1]);
  90.                     }
  91.                     if (sigma == 0) sigma = 1;
  92.                     sigma *= epsilon / (k - 1);
  93.                 }
  94.  
  95.                 double x = std::clamp(gauss_random(mu, sigma), a, b);
  96. //            std::cout << "x: " << x << std::endl;
  97.                 out[i - 1] = x;//double(random_value()) * (b - a) / double(std::default_random_engine::max()) - a;
  98.             }
  99.             return out;
  100.         }
  101.  
  102.         void sort(double q) {
  103.             for (size_t i = 1; i <= k + m; i++) {
  104.                 for (size_t j = i + 1; j <= k + m; j++) {
  105.                     if (f[i - 1] > f[j - 1]) {
  106.                         std::swap(f[i - 1], f[j - 1]);
  107.                         std::swap(s[i - 1], s[j - 1]);
  108.                     }
  109.                 }
  110.             }
  111.         }
  112.  
  113.         void calc_omegas(double q) {
  114.             double koef_1 = 1.0 / (2.0 * q * q * k * k);
  115.             double koef_2 = 1.0 / (q * k * std::sqrt(2.0 * M_PI));
  116.  
  117.             double a = 0;
  118.             double o = koef_1;
  119.  
  120.             for (size_t l = 1; l <= k; l++) {
  121.                 omegas[l - 1] = std::pow(M_E, a) * koef_2;
  122.  
  123.                 a -= o;
  124.                 o += 2.0 * koef_1;
  125.             }
  126.         }
  127.  
  128.         template <typename F>
  129.         void init(F func, double a, double b, double q, double epsilon) {
  130.             for (size_t l = 1; l <= k; l++) {
  131.                 for (size_t i = 1; i <= n; i++) {
  132.                     s[l - 1][i - 1] = double(random_value()) / double(std::default_random_engine::max());
  133.                 }
  134.             }
  135.  
  136.             for (size_t l = 1; l <= k; l++) {
  137.                 f[l - 1] = func(s[l - 1]);
  138.             }
  139.  
  140.             for (size_t ant = 1; ant <= m; ant++) {
  141.                 s[k - 1 + ant] = randomize_s(a, b, ant, q, epsilon);
  142.                 f[k - 1 + ant] = func(s[k + ant - 1]);
  143.             }
  144.             sort(q);
  145.             calc_omegas(q);
  146.         }
  147.  
  148.         template <typename F>
  149.         void step(F func, double a, double b, double q, double epsilon) {
  150.             for (size_t ant = 1; ant <= m; ant++) {
  151.                 s[k - 1 + ant] = construct_s(a, b, ant, q, epsilon);
  152.                 f[k - 1 + ant] = func(s[k + ant - 1]);
  153.             }
  154.             sort(q);
  155.         }
  156.     };
  157.  
  158.     double gauss_random(double mu, double sigma) {
  159.         double w, x1;
  160.         do {
  161.             x1 = 2.0l * (double)(random_value()) / (std::default_random_engine::max() + 1) - 1;
  162.             double x2 = 2.0l * (double)(random_value()) / (std::default_random_engine::max() + 1) - 1;
  163.             w = x1 * x1 + x2 * x2;
  164.         } while (w >= 1.0l);
  165.         return mu + sigma * x1 * std::sqrt(-2.0l * log(w) / w);
  166.     }
  167.  
  168.     template <size_t n>
  169.     using F = double (*)(const Array<double, n>&);
  170.  
  171.     template <size_t k, size_t n, size_t m, size_t maxiter, size_t seed, F<n> func>
  172.     void test(double a, double b, double q, double epsilon) {
  173.         random_engine.seed(seed);
  174. //std::cout << "seed: " << (uint_fast32_t&)random_engine << std::endl;
  175.         auto p = new Archive<double, k, n, m>;
  176.         auto& archive = *p;
  177.  
  178.         archive.init(func, a, b, q, epsilon);
  179.  
  180.         for (size_t iter = 0; iter < maxiter; iter++) {
  181.             archive.step(func, a, b, q, epsilon);
  182.         }
  183.  
  184.         for (size_t l = 1; l <= k; l++) {
  185.             std::cout << /*'|' << std::setw(15) << */archive.f[l - 1] << /*'|' << std::setw(15) << archive.omegas[l - 1]  <<*/ std::endl;
  186.             break;
  187.         }
  188.     }
  189.  
  190.  
  191.     template <size_t d>
  192.     double sphere_function(const Array<double, d>& x) {
  193.         double s = 0;
  194.         for (auto v : x) s += v * v;
  195.         return s;
  196.     }
  197.  
  198.     template <size_t d>
  199.     double ackley_function(const Array<double, d>& x) {
  200.         constexpr double a = - 20.0;
  201.         constexpr double b = 0.2;
  202.         constexpr double c = M_PI * 2.0;
  203.  
  204.         double s1 = std::pow(sphere_function(x) / d, -1.0/b);
  205.         double s2 = 0;
  206.         for (auto v : x) {
  207.             s2 += std::cos(c * v * M_PI / 180.0);
  208.         }
  209.         s2 /= d;
  210.  
  211.         return -a * std::pow(M_E, s1) - std::pow(M_E, s2) + a + M_E;
  212.     }
  213.  
  214.     template <size_t d>
  215.     double grienwank_function(const Array<double, d>& x) {
  216.         double s1 = sphere_function(x) / 4000.0;
  217.         double s2 = 1;
  218.         for (size_t i = 0; i < d; i++) {
  219.             s2 *= std::cos(x[i] * M_PI / 180.0 / std::sqrt(double(i + 1)));
  220.         }
  221.         return s1 - s2 + 1;
  222.     }
  223.  
  224.     template <size_t d>
  225.     double rastrigin_function(const Array<double, d>& x) {
  226.         double s = 0;
  227.         for (auto v : x) {
  228.             s += v * v - 10.0 * std::cos(2.0 * M_PI * v * M_PI / 180.0);
  229.         }
  230.         return 10.0 * double(d) + s;
  231.     }
  232.  
  233.     template <size_t d>
  234.     double rosenbrock_function(const Array<double, d>& x) {
  235.         double s = 0;
  236.         for (size_t i = 0; i < d - 1; i++) {
  237.             double k1 = x[i + 1] - x[i] * x[i];
  238.             double k2 = x[i] - 1;
  239.             s += 100.0 * k1 * k1 + k2 * k2;
  240.         }
  241.         return s;
  242.     }
  243.  
  244.     void run() {
  245.         std::cout << "lab1" << std::endl;
  246.         std::cout << "sphere_function" << std::endl;
  247.         test<50, 50, 100, 10000, 0, sphere_function>(-100, 100, 0.06, 0.05);
  248.         std::cout << std::endl << "ackley_function" << std::endl;
  249.         test<50, 20, 100, 10000, 0, ackley_function>(-32.768, 32.768, 0.06, 0.05);
  250.         std::cout << std::endl << "grienwank_function" << std::endl;
  251.         test<50, 50, 100, 5000, 0, grienwank_function>(-600, 600, 0.06, 0.05);
  252.         std::cout << std::endl << "rastrigin_function" << std::endl;
  253.         test<50, 30, 100, 5000, 0, rastrigin_function>(-5.12, 5.12, 0.06, 0.05);
  254.         std::cout << std::endl << "rosenbrock_function" << std::endl;
  255.         test<50, 30, 100, 10000, 0, rosenbrock_function>(-5, 10, 0.06, 0.05);
  256.     }
  257. }
  258.  
  259. std::ostream &operator<<(std::ostream &out, const std::vector<size_t> &data) {
  260.     if (!data.empty()) {
  261.         out << data[0];
  262.         for (size_t i = 1; i < data.size(); i++) {
  263.             std::cout << " + " << data[i];
  264.         }
  265.     }
  266.     return out;
  267. }
  268.  
  269. namespace {
  270.     template<typename T, typename F>
  271.     std::vector<T> filter(std::vector<T> v, F&& predicate) {
  272.         std::vector<T> result;
  273.         std::copy_if(v.begin(), v.end(), back_inserter(result), std::forward<F>(predicate));
  274.         return std::move(result);
  275.     }
  276. }
  277.  
  278. namespace lab2 {
  279.     std::default_random_engine random_engine(0);
  280.  
  281.     auto random_value() {
  282.         return random_engine();
  283.     }
  284.  
  285.     auto random_double() {
  286.         return random_value() / double(std::default_random_engine::max());
  287.     }
  288.  
  289.     struct Ant {
  290.         const size_t n_cities;
  291.         std::vector<bool> m_visited;
  292.         std::vector<size_t> m_path;
  293.         size_t m_city;
  294.         size_t m_index;
  295.  
  296.         explicit Ant(const size_t cities) : n_cities(cities), m_visited(cities), m_path(cities) {
  297.             clear();
  298.         }
  299.  
  300.         void visit(const size_t city) {
  301.             m_path[m_index++] = city;
  302.             m_visited[city] = true;
  303.             m_city = city;
  304.         }
  305.  
  306.         bool visited(const size_t city) {
  307.             return m_visited[city];
  308.         }
  309.  
  310.         void clear() {
  311.             m_index = 0;
  312.             for (auto && i : m_visited) {
  313.                 i = false;
  314.             }
  315.         }
  316.     };
  317.  
  318.     class AntColonyOptimization {
  319.     public:
  320.         static constexpr double c = 1;
  321.         static constexpr double alpha = 1;
  322.         static constexpr double beta = 5;
  323.         static constexpr double evaporation = 0.5;
  324.         static constexpr double Q = 500;
  325.         static constexpr double randomFactor = 0.01;
  326.  
  327.         static constexpr int maxIterations = 1000;
  328.  
  329.         size_t n_cities;
  330.         size_t n_ants;
  331.         std::vector<size_t> m_graph{};
  332.         std::vector<double> m_pheromones{};
  333.         std::vector<Ant> m_ants{};
  334.         std::vector<double> m_probabilities{};
  335.  
  336.         std::vector<size_t> m_path;
  337.         size_t m_length;
  338.  
  339.         AntColonyOptimization(const std::string &file_name, const int ants) : n_ants(ants) {
  340.             readFromFile(file_name);
  341.  
  342.             m_probabilities.resize(n_cities);
  343.             m_pheromones.resize(n_cities * n_cities);
  344.  
  345.             m_ants.reserve(n_ants);
  346.             for (size_t i = 0; i < n_ants; i++) {
  347.                 m_ants.emplace_back(n_cities);
  348.             }
  349.         }
  350.  
  351.         void readFromFile(const std::string &file_path) {
  352.             std::ifstream file(file_path);
  353.  
  354.             std::string line;
  355.  
  356.             size_t *pgraph;
  357.  
  358.             while (std::getline(file, line)) {
  359.                 std::stringstream ss(line);
  360.  
  361.                 char type;
  362.                 ss >> type;
  363.                 if (type == 'c') continue;
  364.                 if (type == 'p') {
  365.                     ss >> n_cities;
  366.                     m_graph.resize(n_cities * n_cities);
  367.                     pgraph = m_graph.data();
  368.                     continue;
  369.                 }
  370.                 if (type == 'i') {
  371.                     for (size_t i = 0; i < n_cities; i++) {
  372.                         ss >> *pgraph++;
  373.                     }
  374.                 }
  375.             }
  376.         }
  377.  
  378.         void solve() {
  379.             for (double& pheromone : m_pheromones) {
  380.                 pheromone = c;
  381.             }
  382.  
  383.             m_path.clear();
  384.  
  385.             for (size_t i = 0; i < maxIterations; i++) {
  386.                 construct_solutions();
  387.                 update_pheromones();
  388.                 select_best_path();
  389.             }
  390.  
  391.             if (!m_path.empty()) {
  392.                 std::cout << "length: " << m_length << std::endl;
  393. //                std::cout << "path: ";
  394. //                for (size_t city : m_path) {
  395. //                    std::cout << city << ' ';
  396. //                }
  397. //                std::cout << std::endl;
  398.             } else {
  399.                 std::cerr << "no path found" << std::endl;
  400.             }
  401.         }
  402.  
  403.         void construct_solutions() {
  404.             for (Ant& ant : m_ants) {
  405.                 try {
  406.                     generate_solution(ant);
  407.                 } catch (std::runtime_error& e) {
  408.                     ant.clear();
  409.                 }
  410.             }
  411.         }
  412.  
  413.         void generate_solution(Ant& ant) {
  414.             ant.clear();
  415.             ant.visit(0);
  416.  
  417.             for (size_t i = 1; i < n_cities; i++) {
  418.                 ant.visit(select_city(ant));
  419.             }
  420.         }
  421.  
  422.         void calculate_probabilities(Ant& ant) {
  423.             const size_t current_city = ant.m_city;
  424.             const size_t offset = current_city * n_cities;
  425.  
  426.             double probality_of_cities = 0;
  427.             for (size_t city = 0; city < n_cities; city++) {
  428.                 if ((city == current_city) || (m_graph[offset + city] == 0) || ant.visited(city)) continue;
  429.  
  430.                 probality_of_cities += std::pow(m_pheromones[offset + city], alpha) * std::pow(1.0 / m_graph[offset + city], beta);
  431.             }
  432.  
  433.             for (size_t city = 0; city < n_cities; city++) {
  434.                 if ((city == current_city) || (m_graph[offset + city] == 0) || ant.visited(city)) {
  435.                     m_probabilities[city] = 0;
  436.                 } else {
  437.                     m_probabilities[city] = std::pow(m_pheromones[offset + city], alpha) * std::pow(1.0 / m_graph[offset + city], beta) / probality_of_cities;
  438.                 }
  439.             }
  440.         }
  441.  
  442.         size_t select_city(Ant& ant) {
  443.             calculate_probabilities(ant);
  444.  
  445.             double r = random_double();
  446.             double probability = 0;
  447.             for (size_t i = 0; i < n_cities; i++) {
  448.                 probability += m_probabilities[i];
  449.                 if (probability >= r) {
  450.                     return i;
  451.                 }
  452.             }
  453.  
  454.             throw std::runtime_error("no available city");
  455.         }
  456.  
  457.         void update_pheromones() {
  458.             for (double& pheromone : m_pheromones) {
  459.                 pheromone *= (1.0 - evaporation);
  460.             }
  461.  
  462.             for (Ant& ant : m_ants) {
  463.                 if (ant.m_index == 0) continue;
  464.                 for (size_t city : ant.m_path) {
  465.                     const size_t offset = city * n_cities;
  466.  
  467.                     m_pheromones[offset + city] += Q / calculate_length(ant.m_path);
  468.                 }
  469.             }
  470.         }
  471.  
  472.         void select_best_path() {
  473.             for (Ant& ant : m_ants) {
  474.                 if (ant.m_index == 0) continue;
  475.  
  476.                 auto length = calculate_length(ant.m_path);
  477.  
  478.                 if (m_path.empty() || (m_length > length)) {
  479.                     m_path = ant.m_path;
  480.                     m_length = length;
  481.                 }
  482.             }
  483.         }
  484.  
  485.         size_t calculate_length(const std::vector<size_t>& path) {
  486.             size_t length = 0;
  487.  
  488.             for (size_t i = 1; i < n_cities; i++) {
  489.                 length += m_graph[path[i - 1] * n_cities + path[i]];
  490.             }
  491.  
  492.             return length;
  493.         }
  494.     };
  495.  
  496.     void run() {
  497.         std::cout << "lab2" << std::endl;
  498.         std::cout << "yuzSHP55" << std::endl;
  499.         AntColonyOptimization("../yuzSHP55.aco", 20).solve();
  500.         std::cout << std::endl << "yuzSHP95" << std::endl;
  501.         AntColonyOptimization("../yuzSHP95.aco", 20).solve();
  502.         std::cout << std::endl << "yuzSHP155" << std::endl;
  503.         AntColonyOptimization("../yuzSHP155.aco", 20).solve();
  504.     }
  505. }
  506.  
  507. int main() {
  508.     lab1::run();
  509.     std::cout << std::endl;
  510.     lab2::run();
  511.     return 0;
  512. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement