Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <set>
- #include <algorithm>
- #include <limits>
- #include <cmath>
- class Method {
- public:
- virtual void Run(const std::vector<std::vector<double>> &, const std::vector<double> &) = 0;
- virtual ~Method() = default;
- };
- class SawMethod : public Method {
- public:
- void Run(const std::vector<std::vector<double>> &matrix, const std::vector<double> &weights) override {
- double max_score = 0;
- int max_score_index = 0;
- std::vector<double> result;
- for (size_t i = 0; i < matrix.size(); ++i) {
- double temp = 0;
- for (size_t j = 0; j < matrix[i].size(); j++) {
- temp += matrix[i][j] * weights[j];
- }
- temp = std::floor(temp * 1000) / 1000;
- if (temp > max_score) {
- max_score = temp;
- max_score_index = i;
- }
- result.push_back(temp);
- std::cout << "Alternative #" << i + 1 << " has score - " << temp << std::endl;
- }
- std::cout << "Alternative #" << max_score_index + 1 << " better than others. It has score: " << max_score
- << std::endl;
- }
- };
- class ElectreMethod : public Method {
- private:
- std::vector<std::vector<double>> getNormalize(const std::vector<std::vector<double>> &source) const {
- size_t n = source.size();
- size_t m = source.front().size();
- std::vector<std::vector<double>> result(n, std::vector<double>(m, 0));
- for (size_t j = 0; j < m; j++) {
- double max = 0;
- for (size_t i = 0; i < n; ++i) {
- max = std::max(source[i][j], max);
- }
- for (size_t i = 0; i < n; ++i) {
- result[i][j] = source[i][j] / max;
- }
- }
- return std::move(result);
- }
- std::vector<std::vector<double>>
- concordanceMatrix(const std::vector<std::vector<double>> &data, const std::vector<double> &weights) const {
- std::vector<std::vector<double>> result(data.size(), std::vector<double>(data.size(), 0));
- for (size_t i = 0; i < result.size(); i++) {
- for (size_t j = 0; j < result[i].size(); ++j) {
- double sum = 0;
- for (size_t k = 0; k < data.front().size(); ++k) {
- if (data[i][k] >= data[j][k]) {
- sum += weights[k];
- }
- }
- result[i][j] = sum;
- }
- }
- return std::move(result);
- }
- std::vector<std::vector<double>> discordanceMatrix(const std::vector<std::vector<double>> &data) const {
- size_t n = data.size();
- std::vector<std::vector<double>> result(n, std::vector<double>(n, 0));
- for (size_t i = 0; i < n; i++) {
- for (size_t j = 0; j < n; j++) {
- double max = std::numeric_limits<double>::min();
- for (int k = 0; k < data.front().size(); ++k) {
- max = std::max(data[j][k] - data[i][k], max);
- }
- result[i][j] = std::floor(max * 1000) / 1000;
- }
- }
- return std::move(result);
- }
- std::vector<std::vector<bool>> dominanceMatrix(const std::vector<std::vector<double>> &concordance,
- const std::vector<std::vector<double>> &discordance, double c_lim,
- double d_lim) {
- size_t n = concordance.size();
- std::vector<std::vector<bool>> result(n, std::vector<bool>(n, false));
- for (int i = 0; i < n; ++i) {
- for (int j = 0; j < n; ++j) {
- if (concordance[i][j] >= c_lim && discordance[i][j] <= d_lim && i != j) {
- result[i][j] = true;
- }
- }
- }
- return std::move(result);
- }
- public:
- void Run(const std::vector<std::vector<double>> &matrix, const std::vector<double> &weights) override {
- std::vector<std::vector<double>> normalized_matrix(getNormalize(matrix));
- std::vector<std::vector<double>> concordance(concordanceMatrix(normalized_matrix, weights));
- std::vector<std::vector<double>> discordance(discordanceMatrix(normalized_matrix));
- std::vector<std::vector<bool>> dominance(dominanceMatrix(concordance, discordance, 0.45, 0.5));
- // first is sum of elements, second is index
- std::multiset<std::pair<int, int>, std::greater<>> set;
- for (int i = 0; i < dominance.size(); ++i) {
- int sum = 0;
- for (int j = 0; j < dominance[i].size(); ++j) {
- sum += dominance[i][j];
- }
- set.emplace(sum, i);
- }
- int place = 0;
- for (auto it = set.begin(); it != set.end(); ++it) {
- std::cout << "Place #" << ++place << " Alternative #" << it->second + 1 << " - " << it->first << std::endl;
- }
- }
- };
- class TopsisMethod : public Method {
- private:
- std::vector<std::vector<double>> getNormalize(const std::vector<std::vector<double>> &source) const {
- size_t n = source.size();
- size_t m = source.front().size();
- std::vector<std::vector<double>> result(n, std::vector<double>(m, 0));
- for (size_t j = 0; j < m; ++j) {
- double sq = 0;
- for (size_t i = 0; i < n; ++i) {
- sq += source[i][j] * source[i][j];
- }
- sq = std::sqrt(sq);
- for (size_t i = 0; i < n; ++i) {
- result[i][j] = source[i][j] / sq;
- }
- }
- return std::move(result);
- }
- std::vector<double> getWorst(const std::vector<int> &signs, const std::vector<std::vector<double>> &matrix) const {
- std::vector<double> result;
- for (int j = 0; j < matrix.front().size(); ++j) {
- if (signs[j] == 1) {
- double min = std::numeric_limits<double>::max();
- for (int i = 0; i < matrix.size(); ++i) {
- min = std::min(min, matrix[i][j]);
- }
- result.push_back(min);
- } else {
- double max = std::numeric_limits<double>::min();
- for (int i = 0; i < matrix.size(); ++i) {
- max = std::max(max, matrix[i][j]);
- }
- result.push_back(max);
- }
- }
- return std::move(result);
- }
- std::vector<double> getBest(const std::vector<int> &signs, const std::vector<std::vector<double>> &matrix) const {
- std::vector<double> result;
- for (int j = 0; j < matrix.front().size(); ++j) {
- if (signs[j] != 1) {
- double min = std::numeric_limits<double>::max();
- for (int i = 0; i < matrix.size(); ++i) {
- min = std::min(min, matrix[i][j]);
- }
- result.push_back(min);
- } else {
- double max = std::numeric_limits<double>::min();
- for (int i = 0; i < matrix.size(); ++i) {
- max = std::max(max, matrix[i][j]);
- }
- result.push_back(max);
- }
- }
- return std::move(result);
- }
- std::vector<double>
- getDist(const std::vector<std::vector<double>> &matrix, const std::vector<double> &alternatives) {
- std::vector<std::vector<double>> temp(matrix);
- for (int i = 0; i < temp.size(); ++i) {
- for (int j = 0; j < temp.front().size(); ++j) {
- temp[i][j] -= alternatives[j];
- temp[i][j] *= temp[i][j];
- }
- }
- std::vector<double> result(matrix.size());
- for (int i = 0; i < result.size(); ++i) {
- double sum = 0;
- for (int j = 0; j < temp[i].size(); ++j) {
- sum += temp[i][j];
- }
- result[i] = sqrt(sum);
- }
- return std::move(result);
- }
- public:
- void Run(const std::vector<std::vector<double>> &matrix, const std::vector<double> &weights) override {
- auto normalized = getNormalize(matrix);
- for (int i = 0; i < normalized.size(); ++i) {
- for (int j = 0; j < normalized[i].size(); ++j) {
- normalized[i][j] *= weights[j];
- }
- }
- std::vector<int> signs(weights.size(), 1);
- auto worst = getWorst(signs, normalized);
- auto best = getBest(signs, normalized);
- auto worst_distance = getDist(normalized, worst);
- auto best_distance = getDist(normalized, best);
- std::vector<double> res(worst_distance);
- for (int i = 0; i < res.size(); ++i) {
- res[i] /= worst_distance[i] + best_distance[i];
- }
- int max_index = 0;
- int min_index = 0;
- for (int i = 0; i < res.size(); ++i) {
- if (res[max_index] < res[i]) {
- max_index = i;
- }
- if (res[min_index] > res[i]) {
- min_index = i;
- }
- }
- for (int i = 0; i < res.size(); ++i) {
- std::cout << "Alternative #" << i + 1 << " has score - " << res[i] << std::endl;
- }
- std::cout << "Alternative #" << max_index + 1 << " is the best. has score - " << res[max_index] << std::endl;
- std::cout << "Alternative #" << min_index + 1 << " is the worst. has score - " << res[min_index] << std::endl;
- }
- };
- #include <fstream>
- #include <sstream>
- int main() {
- std::vector<std::vector<double>> matrix{
- {3, 3, 3, 5, 3, 2, 2, 3},
- {3, 3, 3, 4, 3, 2, 1, 3},
- {3, 2, 3, 3, 3, 2, 2, 3},
- {2, 5, 4, 2, 2, 1, 2, 3},
- {2, 1, 4, 5, 3, 3, 2, 2}};
- std::vector<double> weights = {0.18, 0.13, 0.17, 0.09, 0.04, 0.13, 0.09, 0.17};
- SawMethod saw;
- saw.Run(matrix, weights);
- ElectreMethod electre;
- electre.Run(matrix, weights);
- TopsisMethod topsis;
- topsis.Run(matrix, weights);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement