From 58982c82c552993e9a22cf9fe34d69d5b66d6ce2 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Fri, 25 Nov 2022 13:17:44 +0100 Subject: [PATCH 01/11] DC node condition included. Additional tests and benchmarks added. Change in the comparator function of MinHeapNode struct --- include/algorithms/synthesis/dd_synthesis.hpp | 2 + include/algorithms/synthesis/encoding.hpp | 2 +- include/core/truthTable/truth_table.hpp | 4 ++ src/algorithms/synthesis/dd_synthesis.cpp | 69 ++++++++++++++----- test/CMakeLists.txt | 3 +- test/circuits/dc3bit.pla | 9 +++ test/circuits/dc3bitNew.pla | 11 +++ test/circuits/dcX2bit.pla | 5 ++ test/circuits/dcX4bit.pla | 7 ++ test/circuits/sym6_32.pla | 36 ++++++++++ test/unittests/test_dd_synthesis_dc.cpp | 51 ++++++++++++++ test/unittests/test_huffman.cpp | 21 +++--- 12 files changed, 191 insertions(+), 29 deletions(-) create mode 100644 test/circuits/dc3bit.pla create mode 100644 test/circuits/dc3bitNew.pla create mode 100644 test/circuits/dcX2bit.pla create mode 100644 test/circuits/dcX4bit.pla create mode 100644 test/circuits/sym6_32.pla create mode 100644 test/unittests/test_dd_synthesis_dc.cpp diff --git a/include/algorithms/synthesis/dd_synthesis.hpp b/include/algorithms/synthesis/dd_synthesis.hpp index 0e0033e0..18ecac0f 100644 --- a/include/algorithms/synthesis/dd_synthesis.hpp +++ b/include/algorithms/synthesis/dd_synthesis.hpp @@ -45,6 +45,8 @@ namespace syrec { static auto controlRoot(dd::mEdge const& current, dd::Controls& ctrl, TruthTable::Cube const& ctrlCube) -> void; static auto controlNonRoot(dd::mEdge const& current, dd::Controls& ctrl, TruthTable::Cube const& ctrlCube) -> void; + static auto dcNodeCondition(dd::mEdge const& current) -> bool; + auto swapPaths(dd::mEdge src, dd::mEdge const& current, TruthTable::Cube::Set const& p1SigVec, TruthTable::Cube::Set const& p2SigVec, std::unique_ptr>& dd) -> dd::mEdge; auto shiftUniquePaths(dd::mEdge src, dd::mEdge const& current, TruthTable::Cube::Set const& p1SigVec, TruthTable::Cube::Set const& p2SigVec, std::unique_ptr>& dd) -> dd::mEdge; diff --git a/include/algorithms/synthesis/encoding.hpp b/include/algorithms/synthesis/encoding.hpp index 22b09760..eb692a39 100644 --- a/include/algorithms/synthesis/encoding.hpp +++ b/include/algorithms/synthesis/encoding.hpp @@ -16,7 +16,7 @@ namespace syrec { data(std::move(data)), freq(freq) {} auto operator>(const MinHeapNode& other) const -> bool { - return freq > other.freq; + return (freq > other.freq || (freq == other.freq && (data > other.data))); } auto traverse(TruthTable::Cube&& encodedCube, TruthTable::CubeMap& encoding) const -> void { diff --git a/include/core/truthTable/truth_table.hpp b/include/core/truthTable/truth_table.hpp index 1ac6926e..a5bec81b 100644 --- a/include/core/truthTable/truth_table.hpp +++ b/include/core/truthTable/truth_table.hpp @@ -136,6 +136,10 @@ namespace syrec { return (cube < cv.cube); } + auto operator>(const Cube& cv) const -> bool { + return (cube > cv.cube); + } + auto operator==(const Cube& cv) const -> bool { return (cube == cv.cube); } diff --git a/src/algorithms/synthesis/dd_synthesis.cpp b/src/algorithms/synthesis/dd_synthesis.cpp index 39f3fc15..03c706bb 100644 --- a/src/algorithms/synthesis/dd_synthesis.cpp +++ b/src/algorithms/synthesis/dd_synthesis.cpp @@ -19,11 +19,20 @@ namespace syrec { for (const auto& [input, output]: tt) { // truth table has to be completely specified assert(input[0].has_value()); - assert(output[0].has_value()); - const auto in = *input[0]; - const auto out = *output[0]; - const auto index = (static_cast(out) * 2U) + static_cast(in); - edges.at(index) = dd::mEdge::one; + + const auto in = *input[0]; + const auto out = *output[0]; + + if (output[0].has_value()) { + const auto index = (static_cast(out) * 2U) + static_cast(in); + edges.at(index) = dd::mEdge::one; + } else if (!in) { + edges.at(0U) = dd::mEdge::one; + edges.at(2U) = dd::mEdge::one; + } else { + edges.at(1U) = dd::mEdge::one; + edges.at(3U) = dd::mEdge::one; + } } return dd->makeDDNode(0, edges); } @@ -33,15 +42,29 @@ namespace syrec { for (const auto& [input, output]: tt) { // truth table has to be completely specified assert(input[0].has_value()); - assert(output[0].has_value()); - const auto in = *input[0]; - const auto out = *output[0]; - const auto index = static_cast(out) * 2U + static_cast(in); - TruthTable::Cube reducedInput(input.begin() + 1, input.end()); - TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); - subTables.at(index).try_emplace(std::move(reducedInput), std::move(reducedOutput)); - } + const auto in = *input[0]; + const auto out = *output[0]; + + if (output[0].has_value()) { + const auto index = static_cast(out) * 2U + static_cast(in); + TruthTable::Cube reducedInput(input.begin() + 1, input.end()); + TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); + subTables.at(index).try_emplace(std::move(reducedInput), std::move(reducedOutput)); + } else { + if (!in) { + TruthTable::Cube reducedInput(input.begin() + 1, input.end()); + TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); + subTables.at(0).try_emplace(reducedInput, reducedOutput); + subTables.at(2).try_emplace(reducedInput, reducedOutput); + } else { + TruthTable::Cube reducedInput(input.begin() + 1, input.end()); + TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); + subTables.at(1).try_emplace(reducedInput, reducedOutput); + subTables.at(3).try_emplace(reducedInput, reducedOutput); + } + } + } // recursively build the DD for each sub-table for (std::size_t i = 0U; i < 4U; ++i) { edges.at(i) = buildDD(subTables.at(i), dd); @@ -181,6 +204,18 @@ namespace syrec { } } + //Checks whether all the edges of the node current is pointing the same node (indicating that the node is a dc Node). + auto DDSynthesizer::dcNodeCondition(dd::mEdge const& current) -> bool { + if (!(dd::mNode::isTerminal(current.p))) { + if (current.p->v == 0U) { + return std::all_of(current.p->e.begin(), current.p->e.end(), [](auto e) { return e == dd::mEdge::one; }); + } + + return std::all_of(current.p->e.begin(), current.p->e.end(), [¤t](auto e) { return e.p == current.p->e[0].p; }); + } + return false; + } + // This function performs the multi-control (if any) X operation. auto DDSynthesizer::applyOperation(dd::QubitCount const& totalBits, dd::Qubit const& targetBit, dd::mEdge& to, dd::Controls const& ctrl, std::unique_ptr>& dd) -> void { // create operation and corresponding decision diagram @@ -354,7 +389,7 @@ namespace syrec { runtime = 0.; numGates = 0U; - if (src.p == nullptr || src.p->isIdentity()) { + if (src.p == nullptr || src.p->isIdentity() || dcNodeCondition(src)) { return qc; } @@ -380,7 +415,7 @@ namespace syrec { const auto current = queue.front(); queue.pop(); - if (current.p == nullptr || current.p->isIdentity()) { + if (current.p == nullptr || current.p->isIdentity() || dcNodeCondition(current)) { continue; } @@ -400,7 +435,7 @@ namespace syrec { if (pathsShifted) { // stopping criterion - if (srcShifted.p->isIdentity()) { + if (srcShifted.p->isIdentity() && dcNodeCondition(srcShifted)) { break; } @@ -414,7 +449,7 @@ namespace syrec { // if all paths have been shifted, the children of the current node need to be processed. for (const auto& e: current.p->e) { - if (!e.isTerminal() && visited.find(e) == visited.end()) { + if (!e.isTerminal() && !dcNodeCondition(e) && visited.find(e) == visited.end()) { queue.emplace(e); visited.emplace(e); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e2eedac0..f7a8c45a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,7 +49,8 @@ package_add_test( unittests/test_extend_tt.cpp unittests/test_huffman.cpp unittests/test_pla_parser.cpp - unittests/test_dd_synthesis.cpp) + unittests/test_dd_synthesis.cpp + unittests/test_dd_synthesis_dc.cpp) add_custom_command( TARGET ${PROJECT_NAME}_test diff --git a/test/circuits/dc3bit.pla b/test/circuits/dc3bit.pla new file mode 100644 index 00000000..6448d161 --- /dev/null +++ b/test/circuits/dc3bit.pla @@ -0,0 +1,9 @@ +.i 3 +.o 3 +00- 0-- +01- 10- +100 111 +101 0-- +110 0-- +111 110 +.e diff --git a/test/circuits/dc3bitNew.pla b/test/circuits/dc3bitNew.pla new file mode 100644 index 00000000..79f8c6d6 --- /dev/null +++ b/test/circuits/dc3bitNew.pla @@ -0,0 +1,11 @@ +.i 3 +.o 3 +000 0-- +001 10- +010 0-- +011 110 +100 10- +101 111 +110 0-- +111 0-- +.e diff --git a/test/circuits/dcX2bit.pla b/test/circuits/dcX2bit.pla new file mode 100644 index 00000000..bf7df1af --- /dev/null +++ b/test/circuits/dcX2bit.pla @@ -0,0 +1,5 @@ +.i 2 +.o 2 +0- 1- +1- 0- +.e diff --git a/test/circuits/dcX4bit.pla b/test/circuits/dcX4bit.pla new file mode 100644 index 00000000..e91cae11 --- /dev/null +++ b/test/circuits/dcX4bit.pla @@ -0,0 +1,7 @@ +.i 4 +.o 4 +00-- 11-- +01-- 10-- +10-- 01-- +11-- 00-- +.e diff --git a/test/circuits/sym6_32.pla b/test/circuits/sym6_32.pla new file mode 100644 index 00000000..d61b0754 --- /dev/null +++ b/test/circuits/sym6_32.pla @@ -0,0 +1,36 @@ +# Function: sym6_32 +# This file has been taken from RevLib (www.revlib.org). +.i 6 +.o 1 +000011 1 +000101 1 +000110 1 +000111 1 +001001 1 +001010 1 +001011 1 +001100 1 +001101 1 +001110 1 +001111 1 +010001 1 +010010 1 +010011 1 +010100 1 +010101 1 +010110 1 +010111 1 +011000 1 +011001 1 +011010 1 +011011 1 +011100 1 +011101 1 +011110 1 +100001 1 +100010 1 +100011 1 +100100 1 +100101 1 +100110 1 +100111 1 diff --git a/test/unittests/test_dd_synthesis_dc.cpp b/test/unittests/test_dd_synthesis_dc.cpp new file mode 100644 index 00000000..89fb7d48 --- /dev/null +++ b/test/unittests/test_dd_synthesis_dc.cpp @@ -0,0 +1,51 @@ +#include "algorithms/synthesis/dd_synthesis.hpp" +#include "algorithms/synthesis/encoding.hpp" +#include "core/io/pla_parser.hpp" + +#include "gtest/gtest.h" + +using namespace dd::literals; +using namespace syrec; + +class TestDDSynthDc: public testing::TestWithParam { +protected: + TruthTable tt{}; + std::string testCircuitsDir = "./circuits/"; + std::unique_ptr> dd = std::make_unique>(15U); + std::string fileName; + + void SetUp() override { + fileName = testCircuitsDir + GetParam() + ".pla"; + } +}; + +INSTANTIATE_TEST_SUITE_P(TestDDSynth, TestDDSynthDc, + testing::Values( + "huff_1", + "dcX2bit", + "dc3bit", + "dc3bitNew", + "dcX4bit", + "sym6_32"), + [](const testing::TestParamInfo& info) { + auto s = info.param; + std::replace( s.begin(), s.end(), '-', '_'); + return s; }); + +TEST_P(TestDDSynthDc, GenericDDSynthesisDcTest) { + EXPECT_TRUE(readPla(tt, fileName)); + extend(tt); + + encodeHuffman(tt); + + const auto ttDD = buildDD(tt, dd); + EXPECT_TRUE(ttDD.p != nullptr); + + DDSynthesizer synthesizer(tt.nInputs()); + const auto& qc = synthesizer.synthesize(ttDD, dd); + + EXPECT_TRUE(!qc.empty()); + + std::cout << synthesizer.numGate() << "\n"; + std::cout << synthesizer.getExecutionTime() << "\n"; +} diff --git a/test/unittests/test_huffman.cpp b/test/unittests/test_huffman.cpp index ea28d424..1259eb93 100644 --- a/test/unittests/test_huffman.cpp +++ b/test/unittests/test_huffman.cpp @@ -1,3 +1,4 @@ + #include "algorithms/synthesis/encoding.hpp" #include "core/io/pla_parser.hpp" @@ -13,7 +14,7 @@ class TestHuff: public testing::Test { }; TEST_F(TestHuff, Ident2Bit) { - std::string circIdent2Bit = testCircuitsDir + "ident2Bit.pla"; + const std::string circIdent2Bit = testCircuitsDir + "ident2Bit.pla"; EXPECT_TRUE(readPla(tt, circIdent2Bit)); @@ -29,7 +30,7 @@ TEST_F(TestHuff, Ident2Bit) { EXPECT_TRUE(search->second.equals(0b00U, 2U)); - TruthTable ttExtend(tt); + const TruthTable ttExtend(tt); encodeHuffman(tt); @@ -37,7 +38,7 @@ TEST_F(TestHuff, Ident2Bit) { } TEST_F(TestHuff, HUFF1) { - std::string circHUFF1 = testCircuitsDir + "huff_1.pla"; + const std::string circHUFF1 = testCircuitsDir + "huff_1.pla"; EXPECT_TRUE(readPla(tt, circHUFF1)); @@ -59,29 +60,29 @@ TEST_F(TestHuff, HUFF1) { EXPECT_EQ(tt.nOutputs(), 2U); - std::vector encInput{0b01U, 0b10U}; + const std::vector encInput{0b01U, 0b10U}; for (const auto& in1: encInput) { auto search = tt.find(in1, 2U); EXPECT_TRUE(search != tt.end()); - EXPECT_TRUE(search->second.equals("0-")); + EXPECT_TRUE(search->second.equals("1-")); } auto search2 = tt.find(0b00U, 2U); EXPECT_TRUE(search2 != tt.end()); - EXPECT_TRUE(search2->second.equals(0b10U, 2U)); + EXPECT_TRUE(search2->second.equals(0b00U, 2U)); auto search3 = tt.find(0b11U, 2U); EXPECT_TRUE(search3 != tt.end()); - EXPECT_TRUE(search3->second.equals(0b11U, 2U)); + EXPECT_TRUE(search3->second.equals(0b01U, 2U)); } TEST_F(TestHuff, HUFF2) { - std::string circHUFF2 = testCircuitsDir + "huff_2.pla"; + const std::string circHUFF2 = testCircuitsDir + "huff_2.pla"; EXPECT_TRUE(readPla(tt, circHUFF2)); @@ -103,7 +104,7 @@ TEST_F(TestHuff, HUFF2) { EXPECT_EQ(tt.nOutputs(), 3U); - std::vector encInput{0b01U, 0b10U, 0b11U}; + const std::vector encInput{0b01U, 0b10U, 0b11U}; for (const auto& in1: encInput) { auto search2 = tt.find(in1, 2U); @@ -124,7 +125,7 @@ TEST_F(TestHuff, HUFF2) { EXPECT_EQ(tt.nInputs(), 3U); - std::vector augInput{0b000U, 0b001U, 0b010U, 0b011U}; + const std::vector augInput{0b000U, 0b001U, 0b010U, 0b011U}; for (const auto& in2: augInput) { auto search4 = tt.find(in2, 3U); From 9f4bfce55e44f6d4d40c6e45dc2cc3c3f351cb8e Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Fri, 25 Nov 2022 18:16:47 +0100 Subject: [PATCH 02/11] Remove assert condition --- src/algorithms/synthesis/encoding.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/algorithms/synthesis/encoding.cpp b/src/algorithms/synthesis/encoding.cpp index 4a087751..7e4252bd 100644 --- a/src/algorithms/synthesis/encoding.cpp +++ b/src/algorithms/synthesis/encoding.cpp @@ -11,9 +11,6 @@ namespace syrec { TruthTable newTT{}; for (auto const& [input, output]: tt) { - // ensure that all outputs are complete - assert(std::none_of(output.cbegin(), output.cend(), [](auto const& v) { return !v.has_value(); })); - // compute the complete cubes for the input auto completeInputs = input.completeCubes(); // move all the complete cubes to the new cube map From 2504065b45c8f810e2fe8a732c70f87918f6a574 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Sat, 26 Nov 2022 11:39:05 +0100 Subject: [PATCH 03/11] Changes based on review comments. --- src/algorithms/synthesis/dd_synthesis.cpp | 28 ++++++++--------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/algorithms/synthesis/dd_synthesis.cpp b/src/algorithms/synthesis/dd_synthesis.cpp index 03c706bb..2a0be0f6 100644 --- a/src/algorithms/synthesis/dd_synthesis.cpp +++ b/src/algorithms/synthesis/dd_synthesis.cpp @@ -26,12 +26,10 @@ namespace syrec { if (output[0].has_value()) { const auto index = (static_cast(out) * 2U) + static_cast(in); edges.at(index) = dd::mEdge::one; - } else if (!in) { - edges.at(0U) = dd::mEdge::one; - edges.at(2U) = dd::mEdge::one; } else { - edges.at(1U) = dd::mEdge::one; - edges.at(3U) = dd::mEdge::one; + const auto offset = in ? 1U : 0U; + edges.at(0U + offset) = dd::mEdge::one; + edges.at(2U + offset) = dd::mEdge::one; } } return dd->makeDDNode(0, edges); @@ -52,17 +50,11 @@ namespace syrec { TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); subTables.at(index).try_emplace(std::move(reducedInput), std::move(reducedOutput)); } else { - if (!in) { - TruthTable::Cube reducedInput(input.begin() + 1, input.end()); - TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); - subTables.at(0).try_emplace(reducedInput, reducedOutput); - subTables.at(2).try_emplace(reducedInput, reducedOutput); - } else { - TruthTable::Cube reducedInput(input.begin() + 1, input.end()); - TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); - subTables.at(1).try_emplace(reducedInput, reducedOutput); - subTables.at(3).try_emplace(reducedInput, reducedOutput); - } + const auto offset = in ? 1U : 0U; + TruthTable::Cube reducedInput(input.begin() + 1, input.end()); + TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); + subTables.at(0 + offset).try_emplace(reducedInput, reducedOutput); + subTables.at(2 + offset).try_emplace(reducedInput, reducedOutput); } } // recursively build the DD for each sub-table @@ -208,10 +200,10 @@ namespace syrec { auto DDSynthesizer::dcNodeCondition(dd::mEdge const& current) -> bool { if (!(dd::mNode::isTerminal(current.p))) { if (current.p->v == 0U) { - return std::all_of(current.p->e.begin(), current.p->e.end(), [](auto e) { return e == dd::mEdge::one; }); + return std::all_of(current.p->e.begin(), current.p->e.end(), [](const auto& e) { return e == dd::mEdge::one; }); } - return std::all_of(current.p->e.begin(), current.p->e.end(), [¤t](auto e) { return e.p == current.p->e[0].p; }); + return std::all_of(current.p->e.begin(), current.p->e.end(), [¤t](const auto& e) { return e.p == current.p->e[0].p; }); } return false; } From 18db92fb20e60c82f3dca7b7e6ccae23f6b5259a Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Sat, 26 Nov 2022 16:12:32 +0100 Subject: [PATCH 04/11] Appropriate test included. --- include/core/truthTable/truth_table.hpp | 41 +++++++++++++++++++++++++ test/unittests/test_dd_synthesis_dc.cpp | 28 +++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/include/core/truthTable/truth_table.hpp b/include/core/truthTable/truth_table.hpp index a5bec81b..47fc6577 100644 --- a/include/core/truthTable/truth_table.hpp +++ b/include/core/truthTable/truth_table.hpp @@ -105,6 +105,47 @@ namespace syrec { return result; } + // return bool vec representation of the cube + [[nodiscard]] auto toBoolVec() const -> std::vector { + assert(cube.size() <= 64U); + assert(std::none_of(cube.cbegin(), cube.cend(), [](auto const& v) { return !v.has_value(); })); + std::vector result; + for (auto const& i: cube) { + result.emplace_back(*i); + } + return result; + } + + // return string representation of the cube + [[nodiscard]] auto toString() const -> std::string { + assert(cube.size() <= 64U); + std::string result; + for (auto const& i: cube) { + if (!i.has_value()) { + result.push_back('-'); + } else if (*i) { + result.push_back('1'); + } else { + result.push_back('0'); + } + } + return result; + } + + // checks if 2 strings are equal irrespective of don't care + [[nodiscard]] static auto equalDcCube(const std::string& in, const std::string& out) -> bool { + for (auto i = 0U; i < in.size(); i++) { + if (in[i] == out[i]) { + continue; + } + if (out[i] == '-') { + continue; + } + return false; + } + return true; + } + [[nodiscard]] auto completeCubes() const -> Vector; auto insertZero() -> void { diff --git a/test/unittests/test_dd_synthesis_dc.cpp b/test/unittests/test_dd_synthesis_dc.cpp index 89fb7d48..ddc4d688 100644 --- a/test/unittests/test_dd_synthesis_dc.cpp +++ b/test/unittests/test_dd_synthesis_dc.cpp @@ -1,6 +1,7 @@ #include "algorithms/synthesis/dd_synthesis.hpp" #include "algorithms/synthesis/encoding.hpp" #include "core/io/pla_parser.hpp" +#include "dd/Simulation.hpp" #include "gtest/gtest.h" @@ -46,6 +47,33 @@ TEST_P(TestDDSynthDc, GenericDDSynthesisDcTest) { EXPECT_TRUE(!qc.empty()); + std::vector inEdges; + inEdges.reserve(tt.size()); + std::vector outputStrings; + outputStrings.reserve(tt.size()); + + for (auto const& [input, output]: tt) { + const std::vector boolCube = input.toBoolVec(); + inEdges.emplace_back(dd->makeBasisState(static_cast(tt.nInputs()), boolCube)); + + TruthTable::Cube reverseCube; + reverseCube.reserve(tt.nInputs()); + + for (auto i = static_cast(tt.nInputs()); i >= 0; i--) { + reverseCube.emplace_back(input[i]); + } + + auto it = tt.find(reverseCube.toInteger(), tt.nInputs()); + + outputStrings.emplace_back(it->second.toString()); + } + + for (auto in = 0U; in < inEdges.size(); in++) { + const auto vOut = dd::simulate(&qc, inEdges[in], dd, 1); + const auto vOutString = vOut.begin()->first; + EXPECT_TRUE(TruthTable::Cube::equalDcCube(vOutString, outputStrings[in])); + } + std::cout << synthesizer.numGate() << "\n"; std::cout << synthesizer.getExecutionTime() << "\n"; } From 9c3a72b2b4200ddf5160ad3aea699abf16f19677 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Sat, 26 Nov 2022 16:53:14 +0100 Subject: [PATCH 05/11] removed the assertion error --- include/core/truthTable/truth_table.hpp | 4 ++++ test/unittests/test_dd_synthesis_dc.cpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/core/truthTable/truth_table.hpp b/include/core/truthTable/truth_table.hpp index 47fc6577..48ac98bd 100644 --- a/include/core/truthTable/truth_table.hpp +++ b/include/core/truthTable/truth_table.hpp @@ -312,6 +312,10 @@ namespace syrec { return cubeMap.find(Cube::fromString(str)); } + auto find(const Cube& c) -> decltype(cubeMap.cbegin()) { + return cubeMap.find(c); + } + auto try_emplace(const Cube& input, const Cube& output) -> void { // NOLINT(readability-identifier-naming) keeping same Interface as std::vector assert(cubeMap.empty() || (input.size() == nInputs() && output.size() == nOutputs())); cubeMap.try_emplace(input, output); diff --git a/test/unittests/test_dd_synthesis_dc.cpp b/test/unittests/test_dd_synthesis_dc.cpp index ddc4d688..6f2ced48 100644 --- a/test/unittests/test_dd_synthesis_dc.cpp +++ b/test/unittests/test_dd_synthesis_dc.cpp @@ -59,11 +59,11 @@ TEST_P(TestDDSynthDc, GenericDDSynthesisDcTest) { TruthTable::Cube reverseCube; reverseCube.reserve(tt.nInputs()); - for (auto i = static_cast(tt.nInputs()); i >= 0; i--) { + for (auto i = static_cast(tt.nInputs()) - 1; i >= 0; i--) { reverseCube.emplace_back(input[i]); } - auto it = tt.find(reverseCube.toInteger(), tt.nInputs()); + auto it = tt.find(reverseCube); outputStrings.emplace_back(it->second.toString()); } From 7b50fef2e2e4512e408350fcf45d1aaabac6ac62 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Sat, 26 Nov 2022 20:30:20 +0100 Subject: [PATCH 06/11] Removed redundant code --- include/core/truthTable/truth_table.hpp | 13 +++++++------ test/unittests/test_dd_synthesis_dc.cpp | 15 ++------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/include/core/truthTable/truth_table.hpp b/include/core/truthTable/truth_table.hpp index 48ac98bd..41c549fb 100644 --- a/include/core/truthTable/truth_table.hpp +++ b/include/core/truthTable/truth_table.hpp @@ -105,13 +105,14 @@ namespace syrec { return result; } - // return bool vec representation of the cube + // return bool vec representation of the cube (order is b0,b1,b2......bn) [[nodiscard]] auto toBoolVec() const -> std::vector { assert(cube.size() <= 64U); assert(std::none_of(cube.cbegin(), cube.cend(), [](auto const& v) { return !v.has_value(); })); std::vector result; - for (auto const& i: cube) { - result.emplace_back(*i); + result.reserve(size()); + for (auto i = static_cast(size()) - 1; i >= 0; i--) { + result.emplace_back(*cube[i]); } return result; } @@ -120,13 +121,13 @@ namespace syrec { [[nodiscard]] auto toString() const -> std::string { assert(cube.size() <= 64U); std::string result; + result.reserve(size()); for (auto const& i: cube) { if (!i.has_value()) { result.push_back('-'); - } else if (*i) { - result.push_back('1'); } else { - result.push_back('0'); + const auto valueChar = *i ? '1' : '0'; + result.push_back(valueChar); } } return result; diff --git a/test/unittests/test_dd_synthesis_dc.cpp b/test/unittests/test_dd_synthesis_dc.cpp index 6f2ced48..6b7f3374 100644 --- a/test/unittests/test_dd_synthesis_dc.cpp +++ b/test/unittests/test_dd_synthesis_dc.cpp @@ -53,19 +53,8 @@ TEST_P(TestDDSynthDc, GenericDDSynthesisDcTest) { outputStrings.reserve(tt.size()); for (auto const& [input, output]: tt) { - const std::vector boolCube = input.toBoolVec(); - inEdges.emplace_back(dd->makeBasisState(static_cast(tt.nInputs()), boolCube)); - - TruthTable::Cube reverseCube; - reverseCube.reserve(tt.nInputs()); - - for (auto i = static_cast(tt.nInputs()) - 1; i >= 0; i--) { - reverseCube.emplace_back(input[i]); - } - - auto it = tt.find(reverseCube); - - outputStrings.emplace_back(it->second.toString()); + inEdges.emplace_back(dd->makeBasisState(static_cast(tt.nInputs()), input.toBoolVec())); + outputStrings.emplace_back(output.toString()); } for (auto in = 0U; in < inEdges.size(); in++) { From bb4314b2a5543d8256f4289a136756014c374191 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Tue, 29 Nov 2022 17:04:30 +0100 Subject: [PATCH 07/11] Changes based on review comments. Included buildTruthTable functionality in simulation. Improved testing. --- .../simulation/simple_simulation.hpp | 5 ++ include/core/truthTable/truth_table.hpp | 60 ++++++++++++------- .../simulation/simple_simulation.cpp | 13 ++++ src/algorithms/synthesis/dd_synthesis.cpp | 13 ++-- test/unittests/test_dd_synthesis_dc.cpp | 18 +----- 5 files changed, 66 insertions(+), 43 deletions(-) diff --git a/include/algorithms/simulation/simple_simulation.hpp b/include/algorithms/simulation/simple_simulation.hpp index 2afc5f5e..eda091fe 100644 --- a/include/algorithms/simulation/simple_simulation.hpp +++ b/include/algorithms/simulation/simple_simulation.hpp @@ -1,7 +1,10 @@ #pragma once +#include "QuantumComputation.hpp" #include "core/circuit.hpp" #include "core/properties.hpp" +#include "core/truthTable/truth_table.hpp" +#include "dd/Simulation.hpp" #include #include @@ -52,4 +55,6 @@ namespace syrec { void simpleSimulation(boost::dynamic_bitset<>& output, const Circuit& circ, const boost::dynamic_bitset<>& input, const Properties::ptr& statistics = Properties::ptr()); + auto buildTruthTable(const qc::QuantumComputation& qc, TruthTable const& tt, std::unique_ptr>& dd) -> TruthTable; + } // namespace syrec diff --git a/include/core/truthTable/truth_table.hpp b/include/core/truthTable/truth_table.hpp index 41c549fb..f347b6ad 100644 --- a/include/core/truthTable/truth_table.hpp +++ b/include/core/truthTable/truth_table.hpp @@ -107,42 +107,41 @@ namespace syrec { // return bool vec representation of the cube (order is b0,b1,b2......bn) [[nodiscard]] auto toBoolVec() const -> std::vector { - assert(cube.size() <= 64U); - assert(std::none_of(cube.cbegin(), cube.cend(), [](auto const& v) { return !v.has_value(); })); - std::vector result; - result.reserve(size()); - for (auto i = static_cast(size()) - 1; i >= 0; i--) { - result.emplace_back(*cube[i]); + assert(std::all_of(cube.cbegin(), cube.cend(), [](auto const& v) { return v.has_value(); })); + const auto nBits = size(); + std::vector result(nBits); + for (std::size_t i = 1U; i <= nBits; ++i) { + result[nBits - i] = *cube[i - 1U]; } return result; } // return string representation of the cube [[nodiscard]] auto toString() const -> std::string { - assert(cube.size() <= 64U); - std::string result; - result.reserve(size()); - for (auto const& i: cube) { + std::stringstream ss{}; + for (const auto& i: cube) { if (!i.has_value()) { - result.push_back('-'); + ss << '-'; } else { - const auto valueChar = *i ? '1' : '0'; - result.push_back(valueChar); + ss << (*i ? '1' : '0'); } } - return result; + return ss.str(); } - // checks if 2 strings are equal irrespective of don't care - [[nodiscard]] static auto equalDcCube(const std::string& in, const std::string& out) -> bool { - for (auto i = 0U; i < in.size(); i++) { - if (in[i] == out[i]) { + // checks if 2 Cubes are equal irrespective of don't care + [[nodiscard]] static auto checkCubeEquality(const Cube& c1, const Cube& c2, const bool equalityUpToDontCare = true) -> bool { + if (c1.size() != c2.size()) { + return false; + } + const auto nBits = c1.size(); + for (auto i = 0U; i < nBits; ++i) { + if (equalityUpToDontCare && (!c1[i].has_value() || !c2[i].has_value())) { continue; } - if (out[i] == '-') { - continue; + if (*c1[i] != *c2[i]) { + return false; } - return false; } return true; } @@ -330,6 +329,25 @@ namespace syrec { cubeMap.insert(std::move(nh)); } + static auto equal(TruthTable& ttOriginal, TruthTable& ttSimOut, const bool equalityUpToDontCare = true) -> bool { + if (ttOriginal.size() != ttSimOut.size()) { + return false; + } + + if (!equalityUpToDontCare) { + return (ttOriginal == ttSimOut); + } + + for (auto const& [input, output]: ttOriginal) { + if (Cube::checkCubeEquality(ttOriginal[input], ttSimOut[input])) { + continue; + } + return false; + } + + return true; + } + auto clear() -> void { cubeMap.clear(); } diff --git a/src/algorithms/simulation/simple_simulation.cpp b/src/algorithms/simulation/simple_simulation.cpp index 162c1f78..7a40f044 100644 --- a/src/algorithms/simulation/simple_simulation.cpp +++ b/src/algorithms/simulation/simple_simulation.cpp @@ -60,4 +60,17 @@ namespace syrec { } } + auto buildTruthTable(const qc::QuantumComputation& qc, TruthTable const& tt, std::unique_ptr>& dd) -> TruthTable { + TruthTable ttSimOut{}; + + for (auto const& [input, _]: tt) { + auto const inEdge = dd->makeBasisState(static_cast(tt.nInputs()), input.toBoolVec()); + const auto out = dd::simulate(&qc, inEdge, dd, 1); + const auto outString = out.begin()->first; + ttSimOut.try_emplace(input, TruthTable::Cube::fromString(outString)); + } + + return ttSimOut; + } + } // namespace syrec diff --git a/src/algorithms/synthesis/dd_synthesis.cpp b/src/algorithms/synthesis/dd_synthesis.cpp index 2a0be0f6..7b191b19 100644 --- a/src/algorithms/synthesis/dd_synthesis.cpp +++ b/src/algorithms/synthesis/dd_synthesis.cpp @@ -44,15 +44,14 @@ namespace syrec { const auto in = *input[0]; const auto out = *output[0]; + TruthTable::Cube reducedInput(input.begin() + 1, input.end()); + TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); + if (output[0].has_value()) { - const auto index = static_cast(out) * 2U + static_cast(in); - TruthTable::Cube reducedInput(input.begin() + 1, input.end()); - TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); + const auto index = static_cast(out) * 2U + static_cast(in); subTables.at(index).try_emplace(std::move(reducedInput), std::move(reducedOutput)); } else { - const auto offset = in ? 1U : 0U; - TruthTable::Cube reducedInput(input.begin() + 1, input.end()); - TruthTable::Cube reducedOutput(output.begin() + 1, output.end()); + const auto offset = in ? 1U : 0U; subTables.at(0 + offset).try_emplace(reducedInput, reducedOutput); subTables.at(2 + offset).try_emplace(reducedInput, reducedOutput); } @@ -196,7 +195,7 @@ namespace syrec { } } - //Checks whether all the edges of the node current is pointing the same node (indicating that the node is a dc Node). + // Check whether all the edges of the current node are pointing to the same node (indicating a don't care node). auto DDSynthesizer::dcNodeCondition(dd::mEdge const& current) -> bool { if (!(dd::mNode::isTerminal(current.p))) { if (current.p->v == 0U) { diff --git a/test/unittests/test_dd_synthesis_dc.cpp b/test/unittests/test_dd_synthesis_dc.cpp index 6b7f3374..5265bd67 100644 --- a/test/unittests/test_dd_synthesis_dc.cpp +++ b/test/unittests/test_dd_synthesis_dc.cpp @@ -1,7 +1,7 @@ +#include "algorithms/simulation/simple_simulation.hpp" #include "algorithms/synthesis/dd_synthesis.hpp" #include "algorithms/synthesis/encoding.hpp" #include "core/io/pla_parser.hpp" -#include "dd/Simulation.hpp" #include "gtest/gtest.h" @@ -47,21 +47,9 @@ TEST_P(TestDDSynthDc, GenericDDSynthesisDcTest) { EXPECT_TRUE(!qc.empty()); - std::vector inEdges; - inEdges.reserve(tt.size()); - std::vector outputStrings; - outputStrings.reserve(tt.size()); + auto ttSimOut = buildTruthTable(qc, tt, dd); - for (auto const& [input, output]: tt) { - inEdges.emplace_back(dd->makeBasisState(static_cast(tt.nInputs()), input.toBoolVec())); - outputStrings.emplace_back(output.toString()); - } - - for (auto in = 0U; in < inEdges.size(); in++) { - const auto vOut = dd::simulate(&qc, inEdges[in], dd, 1); - const auto vOutString = vOut.begin()->first; - EXPECT_TRUE(TruthTable::Cube::equalDcCube(vOutString, outputStrings[in])); - } + EXPECT_TRUE(TruthTable::equal(tt, ttSimOut)); std::cout << synthesizer.numGate() << "\n"; std::cout << synthesizer.getExecutionTime() << "\n"; From f2967caf36d747a40707a37cba19cb9b67da5363 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Tue, 29 Nov 2022 21:22:13 +0100 Subject: [PATCH 08/11] Changes based on review comments. Included buildTruthTable functionality in simulation. Improved testing. --- .../simulation/circuit_to_truthtable.hpp | 11 ++++++++ .../simulation/simple_simulation.hpp | 5 ---- include/core/truthTable/truth_table.hpp | 22 ++++++--------- src/CMakeLists.txt | 2 ++ .../simulation/circuit_to_truthtable.cpp | 28 +++++++++++++++++++ .../simulation/simple_simulation.cpp | 14 ---------- test/unittests/test_dd_synthesis_dc.cpp | 4 +-- 7 files changed, 52 insertions(+), 34 deletions(-) create mode 100644 include/algorithms/simulation/circuit_to_truthtable.hpp create mode 100644 src/algorithms/simulation/circuit_to_truthtable.cpp diff --git a/include/algorithms/simulation/circuit_to_truthtable.hpp b/include/algorithms/simulation/circuit_to_truthtable.hpp new file mode 100644 index 00000000..d9c54f30 --- /dev/null +++ b/include/algorithms/simulation/circuit_to_truthtable.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "QuantumComputation.hpp" +#include "core/truthTable/truth_table.hpp" +#include "dd/Simulation.hpp" + +namespace syrec { + + auto buildTruthTable(const qc::QuantumComputation& qc) -> TruthTable; + +} // namespace syrec diff --git a/include/algorithms/simulation/simple_simulation.hpp b/include/algorithms/simulation/simple_simulation.hpp index eda091fe..2afc5f5e 100644 --- a/include/algorithms/simulation/simple_simulation.hpp +++ b/include/algorithms/simulation/simple_simulation.hpp @@ -1,10 +1,7 @@ #pragma once -#include "QuantumComputation.hpp" #include "core/circuit.hpp" #include "core/properties.hpp" -#include "core/truthTable/truth_table.hpp" -#include "dd/Simulation.hpp" #include #include @@ -55,6 +52,4 @@ namespace syrec { void simpleSimulation(boost::dynamic_bitset<>& output, const Circuit& circ, const boost::dynamic_bitset<>& input, const Properties::ptr& statistics = Properties::ptr()); - auto buildTruthTable(const qc::QuantumComputation& qc, TruthTable const& tt, std::unique_ptr>& dd) -> TruthTable; - } // namespace syrec diff --git a/include/core/truthTable/truth_table.hpp b/include/core/truthTable/truth_table.hpp index f347b6ad..645421f2 100644 --- a/include/core/truthTable/truth_table.hpp +++ b/include/core/truthTable/truth_table.hpp @@ -110,8 +110,8 @@ namespace syrec { assert(std::all_of(cube.cbegin(), cube.cend(), [](auto const& v) { return v.has_value(); })); const auto nBits = size(); std::vector result(nBits); - for (std::size_t i = 1U; i <= nBits; ++i) { - result[nBits - i] = *cube[i - 1U]; + for (std::size_t i = 0U; i < nBits; ++i) { + result[nBits - 1 - i] = *cube[i]; } return result; } @@ -329,22 +329,18 @@ namespace syrec { cubeMap.insert(std::move(nh)); } - static auto equal(TruthTable& ttOriginal, TruthTable& ttSimOut, const bool equalityUpToDontCare = true) -> bool { - if (ttOriginal.size() != ttSimOut.size()) { - return false; - } - + static auto equal(TruthTable& tt1, TruthTable& tt2, const bool equalityUpToDontCare = true) -> bool { if (!equalityUpToDontCare) { - return (ttOriginal == ttSimOut); + return (tt1 == tt2); } - - for (auto const& [input, output]: ttOriginal) { - if (Cube::checkCubeEquality(ttOriginal[input], ttSimOut[input])) { + for (auto const& [input, output]: tt1) { + if (auto it = tt2.find(input); it == tt2.end()) { continue; } - return false; + if (!Cube::checkCubeEquality(tt1[input], tt2[input])) { + return false; + } } - return true; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fdcce13b..a5d69b5d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,11 +4,13 @@ add_library( ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/synthesis/syrec_cost_aware_synthesis.cpp ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/synthesis/syrec_line_aware_synthesis.cpp ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/simulation/simple_simulation.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/simulation/circuit_to_truthtable.cpp ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/synthesis/dd_synthesis.cpp ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/synthesis/encoding.cpp ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/optimization/esop_minimization.cpp ${${PROJECT_NAME}_SOURCE_DIR}/include/algorithms/optimization/esop_minimization.hpp ${${PROJECT_NAME}_SOURCE_DIR}/include/algorithms/simulation/simple_simulation.hpp + ${${PROJECT_NAME}_SOURCE_DIR}/include/algorithms/simulation/circuit_to_truthtable.hpp ${${PROJECT_NAME}_SOURCE_DIR}/include/algorithms/synthesis/syrec_synthesis.hpp ${${PROJECT_NAME}_SOURCE_DIR}/include/algorithms/synthesis/syrec_cost_aware_synthesis.hpp ${${PROJECT_NAME}_SOURCE_DIR}/include/algorithms/synthesis/syrec_line_aware_synthesis.hpp diff --git a/src/algorithms/simulation/circuit_to_truthtable.cpp b/src/algorithms/simulation/circuit_to_truthtable.cpp new file mode 100644 index 00000000..31df0e2b --- /dev/null +++ b/src/algorithms/simulation/circuit_to_truthtable.cpp @@ -0,0 +1,28 @@ +#include "algorithms/simulation/circuit_to_truthtable.hpp" + +namespace syrec { + + auto buildTruthTable(const qc::QuantumComputation& qc) -> TruthTable { + TruthTable ttSimOut{}; + const auto nBits = qc.getNqubits(); + auto dd = std::make_unique>(nBits); + + const auto totalInputs = 1U << nBits; + + std::uint64_t n = 0U; + + while (n < totalInputs) { + const auto inCube = TruthTable::Cube::fromInteger(n, nBits); + + auto const inEdge = dd->makeBasisState(nBits, inCube.toBoolVec()); + const auto out = dd::simulate(&qc, inEdge, dd, 1); + const auto outString = out.begin()->first; + + ttSimOut.try_emplace(inCube, TruthTable::Cube::fromString(outString)); + ++n; + } + + return ttSimOut; + } + +} // namespace syrec diff --git a/src/algorithms/simulation/simple_simulation.cpp b/src/algorithms/simulation/simple_simulation.cpp index 7a40f044..6f8387dd 100644 --- a/src/algorithms/simulation/simple_simulation.cpp +++ b/src/algorithms/simulation/simple_simulation.cpp @@ -59,18 +59,4 @@ namespace syrec { t.stop(); } } - - auto buildTruthTable(const qc::QuantumComputation& qc, TruthTable const& tt, std::unique_ptr>& dd) -> TruthTable { - TruthTable ttSimOut{}; - - for (auto const& [input, _]: tt) { - auto const inEdge = dd->makeBasisState(static_cast(tt.nInputs()), input.toBoolVec()); - const auto out = dd::simulate(&qc, inEdge, dd, 1); - const auto outString = out.begin()->first; - ttSimOut.try_emplace(input, TruthTable::Cube::fromString(outString)); - } - - return ttSimOut; - } - } // namespace syrec diff --git a/test/unittests/test_dd_synthesis_dc.cpp b/test/unittests/test_dd_synthesis_dc.cpp index 5265bd67..2b528095 100644 --- a/test/unittests/test_dd_synthesis_dc.cpp +++ b/test/unittests/test_dd_synthesis_dc.cpp @@ -1,4 +1,4 @@ -#include "algorithms/simulation/simple_simulation.hpp" +#include "algorithms/simulation/circuit_to_truthtable.hpp" #include "algorithms/synthesis/dd_synthesis.hpp" #include "algorithms/synthesis/encoding.hpp" #include "core/io/pla_parser.hpp" @@ -47,7 +47,7 @@ TEST_P(TestDDSynthDc, GenericDDSynthesisDcTest) { EXPECT_TRUE(!qc.empty()); - auto ttSimOut = buildTruthTable(qc, tt, dd); + auto ttSimOut = buildTruthTable(qc); EXPECT_TRUE(TruthTable::equal(tt, ttSimOut)); From 7d8204d79875820a4630709477468e3816b1e400 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Tue, 29 Nov 2022 21:57:21 +0100 Subject: [PATCH 09/11] Changes based on review comments. --- include/algorithms/simulation/circuit_to_truthtable.hpp | 2 +- src/algorithms/simulation/circuit_to_truthtable.cpp | 7 ++----- test/unittests/test_dd_synthesis_dc.cpp | 5 +++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/algorithms/simulation/circuit_to_truthtable.hpp b/include/algorithms/simulation/circuit_to_truthtable.hpp index d9c54f30..30059f39 100644 --- a/include/algorithms/simulation/circuit_to_truthtable.hpp +++ b/include/algorithms/simulation/circuit_to_truthtable.hpp @@ -6,6 +6,6 @@ namespace syrec { - auto buildTruthTable(const qc::QuantumComputation& qc) -> TruthTable; + auto buildTruthTable(const qc::QuantumComputation& qc, TruthTable& tt) -> void; } // namespace syrec diff --git a/src/algorithms/simulation/circuit_to_truthtable.cpp b/src/algorithms/simulation/circuit_to_truthtable.cpp index 31df0e2b..6d105dbf 100644 --- a/src/algorithms/simulation/circuit_to_truthtable.cpp +++ b/src/algorithms/simulation/circuit_to_truthtable.cpp @@ -2,8 +2,7 @@ namespace syrec { - auto buildTruthTable(const qc::QuantumComputation& qc) -> TruthTable { - TruthTable ttSimOut{}; + auto buildTruthTable(const qc::QuantumComputation& qc, TruthTable& tt) -> void { const auto nBits = qc.getNqubits(); auto dd = std::make_unique>(nBits); @@ -18,11 +17,9 @@ namespace syrec { const auto out = dd::simulate(&qc, inEdge, dd, 1); const auto outString = out.begin()->first; - ttSimOut.try_emplace(inCube, TruthTable::Cube::fromString(outString)); + tt.try_emplace(inCube, TruthTable::Cube::fromString(outString)); ++n; } - - return ttSimOut; } } // namespace syrec diff --git a/test/unittests/test_dd_synthesis_dc.cpp b/test/unittests/test_dd_synthesis_dc.cpp index 2b528095..8ecccfe5 100644 --- a/test/unittests/test_dd_synthesis_dc.cpp +++ b/test/unittests/test_dd_synthesis_dc.cpp @@ -11,6 +11,7 @@ using namespace syrec; class TestDDSynthDc: public testing::TestWithParam { protected: TruthTable tt{}; + TruthTable ttqc{}; std::string testCircuitsDir = "./circuits/"; std::unique_ptr> dd = std::make_unique>(15U); std::string fileName; @@ -47,9 +48,9 @@ TEST_P(TestDDSynthDc, GenericDDSynthesisDcTest) { EXPECT_TRUE(!qc.empty()); - auto ttSimOut = buildTruthTable(qc); + buildTruthTable(qc, ttqc); - EXPECT_TRUE(TruthTable::equal(tt, ttSimOut)); + EXPECT_TRUE(TruthTable::equal(tt, ttqc)); std::cout << synthesizer.numGate() << "\n"; std::cout << synthesizer.getExecutionTime() << "\n"; From e3029c7a33e5ef41579dc09ffc0a3dde3e6d4a45 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Wed, 30 Nov 2022 00:25:46 +0100 Subject: [PATCH 10/11] Changes based on review comments. --- include/algorithms/simulation/circuit_to_truthtable.hpp | 1 - include/core/truthTable/truth_table.hpp | 3 --- src/algorithms/simulation/circuit_to_truthtable.cpp | 6 +++++- test/unittests/test_dd_synthesis_dc.cpp | 2 -- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/algorithms/simulation/circuit_to_truthtable.hpp b/include/algorithms/simulation/circuit_to_truthtable.hpp index 30059f39..0579ebd5 100644 --- a/include/algorithms/simulation/circuit_to_truthtable.hpp +++ b/include/algorithms/simulation/circuit_to_truthtable.hpp @@ -2,7 +2,6 @@ #include "QuantumComputation.hpp" #include "core/truthTable/truth_table.hpp" -#include "dd/Simulation.hpp" namespace syrec { diff --git a/include/core/truthTable/truth_table.hpp b/include/core/truthTable/truth_table.hpp index 645421f2..021bd1ac 100644 --- a/include/core/truthTable/truth_table.hpp +++ b/include/core/truthTable/truth_table.hpp @@ -334,9 +334,6 @@ namespace syrec { return (tt1 == tt2); } for (auto const& [input, output]: tt1) { - if (auto it = tt2.find(input); it == tt2.end()) { - continue; - } if (!Cube::checkCubeEquality(tt1[input], tt2[input])) { return false; } diff --git a/src/algorithms/simulation/circuit_to_truthtable.cpp b/src/algorithms/simulation/circuit_to_truthtable.cpp index 6d105dbf..4665a2a3 100644 --- a/src/algorithms/simulation/circuit_to_truthtable.cpp +++ b/src/algorithms/simulation/circuit_to_truthtable.cpp @@ -1,10 +1,14 @@ #include "algorithms/simulation/circuit_to_truthtable.hpp" +#include "dd/Simulation.hpp" + namespace syrec { auto buildTruthTable(const qc::QuantumComputation& qc, TruthTable& tt) -> void { const auto nBits = qc.getNqubits(); - auto dd = std::make_unique>(nBits); + assert(nBits < 65U); + + auto dd = std::make_unique>(nBits); const auto totalInputs = 1U << nBits; diff --git a/test/unittests/test_dd_synthesis_dc.cpp b/test/unittests/test_dd_synthesis_dc.cpp index 8ecccfe5..e241c400 100644 --- a/test/unittests/test_dd_synthesis_dc.cpp +++ b/test/unittests/test_dd_synthesis_dc.cpp @@ -46,8 +46,6 @@ TEST_P(TestDDSynthDc, GenericDDSynthesisDcTest) { DDSynthesizer synthesizer(tt.nInputs()); const auto& qc = synthesizer.synthesize(ttDD, dd); - EXPECT_TRUE(!qc.empty()); - buildTruthTable(qc, ttqc); EXPECT_TRUE(TruthTable::equal(tt, ttqc)); From 1ef4b395201ea06a617a7e6ff9d7b301c30255d8 Mon Sep 17 00:00:00 2001 From: SmaranTum Date: Wed, 30 Nov 2022 02:20:04 +0100 Subject: [PATCH 11/11] Changes based on review comments. --- include/core/truthTable/truth_table.hpp | 12 +-------- src/core/truthTable/truth_table.cpp | 34 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/include/core/truthTable/truth_table.hpp b/include/core/truthTable/truth_table.hpp index 021bd1ac..4c120f15 100644 --- a/include/core/truthTable/truth_table.hpp +++ b/include/core/truthTable/truth_table.hpp @@ -329,17 +329,7 @@ namespace syrec { cubeMap.insert(std::move(nh)); } - static auto equal(TruthTable& tt1, TruthTable& tt2, const bool equalityUpToDontCare = true) -> bool { - if (!equalityUpToDontCare) { - return (tt1 == tt2); - } - for (auto const& [input, output]: tt1) { - if (!Cube::checkCubeEquality(tt1[input], tt2[input])) { - return false; - } - } - return true; - } + static auto equal(TruthTable& tt1, TruthTable& tt2, bool equalityUpToDontCare = true) -> bool; auto clear() -> void { cubeMap.clear(); diff --git a/src/core/truthTable/truth_table.cpp b/src/core/truthTable/truth_table.cpp index 69b47db2..f6a4e4bc 100644 --- a/src/core/truthTable/truth_table.cpp +++ b/src/core/truthTable/truth_table.cpp @@ -39,4 +39,38 @@ namespace syrec { return result; } + auto TruthTable::equal(TruthTable& tt1, TruthTable& tt2, bool equalityUpToDontCare) -> bool { + if (!equalityUpToDontCare) { + return (tt1 == tt2); + } + + if (tt1.nInputs() != tt2.nInputs()) { + return false; + } + + const auto nBits = tt1.nInputs(); + assert(nBits < 65U); + const auto totalInputs = 1U << nBits; + + std::uint64_t n = 0U; + + while (n < totalInputs) { + const auto input = TruthTable::Cube::fromInteger(n, nBits); + ++n; + + const auto foundtt1 = tt1.find(input) != tt1.end(); + const auto foundtt2 = tt2.find(input) != tt2.end(); + + if (!foundtt1 || !foundtt2) { + continue; + } + + if (!Cube::checkCubeEquality(tt1[input], tt2[input])) { + return false; + } + } + + return true; + } + } // namespace syrec