Advertisement
Hamikadze

Untitled

Jan 15th, 2019
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.98 KB | None | 0 0
  1. #include "pch.h"
  2. #include <array>
  3. #include <vector>
  4. #include <bitset>
  5. #include <fstream>
  6. #include <functional>
  7. #include <type_traits>
  8. #include <string>
  9. #include <sstream>
  10. #include <iostream>
  11.  
  12. class GameOfLifeCnf
  13. {
  14.     template <size_t N>
  15.     using Mask = std::bitset<N>;
  16.     template <size_t N>
  17.     using Masks = std::vector<Mask<N>>;
  18.  
  19. private:
  20.     struct MaskSize
  21.     {
  22.         static const uint32_t REGULAR = 9, SIDE = 6, CORNER = 4;
  23.     };
  24.  
  25.     enum class MaskType : uint_fast32_t {
  26.         REGULAR,
  27.         LEFT, TOP, RIGHT, BOTTOM,
  28.         LEFT_TOP, RIGHT_TOP, LEFT_BOTTOM, RIGHT_BOTTOM
  29.     };
  30.  
  31.     template <typename ...Bits>
  32.     static constexpr auto convertMasks(const std::vector<std::bitset<MaskSize::REGULAR>> & masks, Bits... bits) {
  33.         static_assert((std::is_convertible<Bits, uint32_t>::value && ...));
  34.  
  35.         std::vector<std::bitset<MaskSize::REGULAR - sizeof...(Bits)>> newMasks;
  36.         for (const auto & mask : masks) {
  37.             if ((mask.test(bits) && ...)) {
  38.                 std::bitset<MaskSize::REGULAR - sizeof...(Bits)> newMask;
  39.                 uint32_t index = 0;
  40.                 for (uint32_t i = 0; i < MaskSize::REGULAR; ++i) {
  41.                     if (((i != bits) && ...))
  42.                         newMask[index++] = mask.test(i);
  43.                 }
  44.                 newMasks.emplace_back(newMask);
  45.             }
  46.         }
  47.  
  48.         return newMasks;
  49.     }
  50.  
  51.     template <MaskType Type = MaskType::REGULAR>
  52.     auto getVarNumbers(uint32_t param1 = 0, uint32_t param2 = 0)
  53.     {
  54.         std::function<int32_t(uint32_t)> calcLiteral;
  55.         if constexpr (Type == MaskType::REGULAR)
  56.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return 1 + columns_ + 2 + 1 + (param1 + index / 3 - 1) * (columns_ + 2) + (param2 + index % 3 - 1); };
  57.         else if constexpr (Type == MaskType::LEFT)
  58.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return 1 + (param1 + index / 2 - 1) * (columns_ + 2) + index % 2; };
  59.         else if constexpr (Type == MaskType::TOP)
  60.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return param1 + index / 3 * (columns_ + 2) + index % 3; };
  61.         else if constexpr (Type == MaskType::RIGHT)
  62.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return 1 + columns_ + (param1 + index / 2 - 1) * (columns_ + 2) + index % 2; };
  63.         else if constexpr (Type == MaskType::BOTTOM)
  64.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return param1 + (rows_ + index / 3) * (columns_ + 2) + index % 3; };
  65.         else if constexpr (Type == MaskType::LEFT_TOP)
  66.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return 1 + index / 2 * (columns_ + 2) + index % 2; };
  67.         else if constexpr (Type == MaskType::RIGHT_TOP)
  68.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return 1 + columns_ + (index / 2)*(columns_ + 2) + index % 2; };
  69.         else if constexpr (Type == MaskType::LEFT_BOTTOM)
  70.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return 1 + (rows_ + index / 2) * (columns_ + 2) + index % 2; };
  71.         else if constexpr (Type == MaskType::RIGHT_BOTTOM)
  72.             calcLiteral = [&](const uint32_t index) constexpr->int32_t { return 1 + columns_ + (rows_ + index / 2) * (columns_ + 2) + index % 2; };
  73.         else
  74.             throw std::exception();
  75.  
  76.         constexpr uint32_t varNum = Type == MaskType::REGULAR ? MaskSize::REGULAR : Type == MaskType::LEFT || Type == MaskType::TOP || Type == MaskType::RIGHT || Type == MaskType::BOTTOM ? MaskSize::SIDE : MaskSize::CORNER;
  77.         std::array<int32_t, varNum> literals;
  78.         for (uint32_t i = 0; i < varNum; i++)
  79.             literals[i] = calcLiteral(i);
  80.  
  81.         return literals;
  82.     }
  83.  
  84.     // вывод литералов
  85.     template <size_t N>
  86.     void outputLiterals(const std::array<int32_t, N> & literals) {
  87.         cnf_ << '(';
  88.         for (size_t i = 0; i < literals.size(); i++) {
  89.             if (literals[i] < 0) {
  90.                 cnf_ << '~' << 'x' << -literals[i];
  91.             }
  92.             else
  93.                 cnf_ << 'x' << literals[i];
  94.  
  95.             dimacs_ << literals[i] << " ";
  96.             if (i != literals.size() - 1)
  97.                 cnf_ << '|';
  98.         }
  99.         dimacs_ << "0\n";
  100.         cnf_ << ')';
  101.     }
  102.  
  103.     template <size_t N>
  104.     void handleMasks(const std::vector<std::bitset<N>> & masks, const std::array<int32_t, N> &varNumbers) {
  105.         for (const auto &mask : masks) {
  106.             auto literals = varNumbers;
  107.             for (uint32_t i = 0; i < N; i++) {
  108.                 if (!mask.test(i))
  109.                     literals[i] = -literals[i];
  110.             }
  111.             outputLiterals(literals);
  112.         }
  113.     }
  114.  
  115.     // вспомогательные функции
  116.     static constexpr auto numberOfSetBits(uint32_t i) {
  117.         i = i - ((i >> 1) & 0x55555555);
  118.         i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
  119.         return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
  120.     }
  121.  
  122.     static constexpr auto assembleMask(const uint8_t params, const bool e) {
  123.         return ~(uint32_t(params & 0xF0) << 1 | (params & 0xF) | e << 4);
  124.     }
  125.  
  126.     static Masks<MaskSize::REGULAR> cnfMasksLive, cnfMasksDead;
  127.     static Masks<MaskSize::SIDE> cnfLeft, cnfTop, cnfRight, cnfBottom;
  128.     static Masks<MaskSize::CORNER> cnfLeftTop, cnfRightTop, cnfLeftBottom, cnfRightBottom;
  129.  
  130.     size_t columns_, rows_;
  131.     std::stringstream cnf_, dimacs_;
  132.  
  133. public:
  134.     static void init()
  135.     {
  136.         // строим маски КНФ
  137.         for (uint32_t i = 0; i < 1 << 8; i++) {
  138.             const auto sb = numberOfSetBits(i);
  139.             if (sb != 3) {
  140.                 cnfMasksLive.emplace_back(assembleMask(i, false));
  141.                 if (sb != 2)
  142.                     cnfMasksLive.emplace_back(assembleMask(i, true));
  143.                 else
  144.                     cnfMasksDead.emplace_back(assembleMask(i, true));
  145.             }
  146.             else {
  147.                 cnfMasksDead.emplace_back(assembleMask(i, true));
  148.                 cnfMasksDead.emplace_back(assembleMask(i, false));
  149.             }
  150.         }
  151.         // маски добавочных клеток
  152.         cnfLeft = convertMasks(cnfMasksDead, 0, 3, 6);
  153.         cnfTop = convertMasks(cnfMasksDead, 0, 1, 2);
  154.         cnfRight = convertMasks(cnfMasksDead, 2, 5, 8);
  155.         cnfBottom = convertMasks(cnfMasksDead, 6, 7, 8);
  156.         cnfLeftTop = convertMasks(cnfMasksDead, 0, 1, 2, 3, 6);
  157.         cnfRightTop = convertMasks(cnfMasksDead, 0, 1, 2, 5, 8);
  158.         cnfLeftBottom = convertMasks(cnfMasksDead, 0, 3, 6, 7, 8);
  159.         cnfRightBottom = convertMasks(cnfMasksDead, 2, 5, 6, 7, 8);
  160.     }
  161.  
  162.     GameOfLifeCnf(const size_t rows, const size_t columns, const std::vector<bool> & configuration) : columns_(columns), rows_(rows)
  163.     {
  164.         // пишем КНФ и DIMACS
  165.         const auto liveNum = std::count_if(configuration.begin(), configuration.end(), [](const bool val) { return val; });
  166.         const auto varNum = (rows + 2)*(columns + 2);
  167.         const auto clauseNum = cnfMasksLive.size() * liveNum + cnfMasksDead.size() * (varNum - liveNum) +
  168.             cnfLeftTop.size() + cnfRightTop.size() + cnfLeftBottom.size() + cnfRightBottom.size() + rows * (cnfLeft.size() + cnfRight.size()) + columns * (cnfTop.size() + cnfBottom.size());
  169.         dimacs_ << "p cnf " << varNum << ' ' << clauseNum << '\n';
  170.  
  171.         // КНФ клеток конфигурации
  172.         for (uint32_t i = 0; i < rows; i++) {
  173.             for (uint32_t j = 0; j < columns; j++) {
  174.                 const auto & masks = configuration[i*columns + j] ? cnfMasksLive : cnfMasksDead;
  175.                 const auto varNumbers = getVarNumbers(i, j);
  176.                 handleMasks(masks, varNumbers);
  177.             }
  178.         }
  179.  
  180.         // КНФ внешних клеток
  181.         auto varNumbers = getVarNumbers<MaskType::LEFT_TOP>();
  182.         handleMasks(cnfLeftTop, varNumbers);
  183.         varNumbers = getVarNumbers<MaskType::RIGHT_TOP>();
  184.         handleMasks(cnfRightTop, varNumbers);
  185.         varNumbers = getVarNumbers<MaskType::LEFT_BOTTOM>();
  186.         handleMasks(cnfLeftBottom, varNumbers);
  187.         varNumbers = getVarNumbers<MaskType::RIGHT_BOTTOM>();
  188.         handleMasks(cnfRightBottom, varNumbers);
  189.  
  190.         for (uint32_t i = 1; i <= rows; i++) {
  191.             auto varNumbers = getVarNumbers<MaskType::LEFT>(i);
  192.             handleMasks(cnfLeft, varNumbers);
  193.             varNumbers = getVarNumbers<MaskType::RIGHT>(i);
  194.             handleMasks(cnfRight, varNumbers);
  195.         }
  196.  
  197.         for (uint32_t i = 1; i <= columns; i++) {
  198.             auto varNumbers = getVarNumbers<MaskType::TOP>(i);
  199.             handleMasks(cnfTop, varNumbers);
  200.             varNumbers = getVarNumbers<MaskType::BOTTOM>(i);
  201.             handleMasks(cnfBottom, varNumbers);
  202.         }
  203.     }
  204.  
  205.     auto getCnf() const
  206.     {
  207.         return cnf_.str();
  208.     }
  209.  
  210.     auto getDimacs() const
  211.     {
  212.         return dimacs_.str();
  213.     }
  214. };
  215.  
  216. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::REGULAR> GameOfLifeCnf::cnfMasksLive = {};
  217. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::REGULAR> GameOfLifeCnf::cnfMasksDead = {};
  218. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::SIDE> GameOfLifeCnf::cnfLeft = {};
  219. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::SIDE> GameOfLifeCnf::cnfTop = {};
  220. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::SIDE> GameOfLifeCnf::cnfRight = {};
  221. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::SIDE> GameOfLifeCnf::cnfBottom = {};
  222. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::CORNER> GameOfLifeCnf::cnfLeftTop = {};
  223. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::CORNER> GameOfLifeCnf::cnfRightTop = {};
  224. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::CORNER> GameOfLifeCnf::cnfLeftBottom = {};
  225. GameOfLifeCnf::Masks<GameOfLifeCnf::MaskSize::CORNER> GameOfLifeCnf::cnfRightBottom = {};
  226.  
  227. int main() {
  228.     auto out = std::ofstream("output.txt");
  229.     auto outDimacs = std::ofstream("dimacs.cnf");
  230.  
  231.     try {
  232.         GameOfLifeCnf::init();
  233.         GameOfLifeCnf cnf(3, 3, {
  234.             0,1,0,
  235.             1,0,1,
  236.             1,0,0 });
  237.  
  238.         out << cnf.getCnf();
  239.         outDimacs << cnf.getDimacs();
  240.     }
  241.     catch (const std::exception & e)
  242.     {
  243.         std::cerr << e.what();
  244.     }
  245. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement