1 /* 2 * This file is part of Quantum++. 3 * 4 * Copyright (c) 2013 - 2021 softwareQ Inc. All rights reserved. 5 * 6 * MIT License 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to deal 10 * in the Software without restriction, including without limitation the rights 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 * copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in 16 * all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 * SOFTWARE. 25 */ 26 27 /** 28 * \file classes/codes.hpp 29 * \brief Quantum error correcting codes 30 */ 31 32 #ifndef CLASSES_CODES_HPP_ 33 #define CLASSES_CODES_HPP_ 34 35 namespace qpp { 36 /** 37 * \class qpp::Codes 38 * \brief const Singleton class that defines quantum error correcting codes 39 */ 40 class Codes final : public internal::Singleton<const Codes> // const Singleton 41 { 42 friend class internal::Singleton<const Codes>; 43 44 public: 45 /** 46 * \brief Code types, add more codes here if needed 47 * \see qpp::Codes::codeword() 48 */ 49 enum class Type { 50 FIVE_QUBIT, ///< [[5,1,3]] qubit code 51 STEANE_SEVEN_QUBIT, ///< [[7,1,3]] Steane qubit code 52 SHOR_NINE_QUBIT, ///< [[9,1,3]] Shor qubit code 53 }; 54 55 private: 56 /** 57 * \brief Default constructor 58 */ Codes()59 Codes() {} // = default; // clang++ spits the error below if defaulted: 60 // error: 61 // default initialization of an object of const type 'const qpp::Codes' 62 // requires a user-provided default constructor 63 64 /** 65 * \brief Default destructor 66 */ 67 ~Codes() override = default; 68 69 public: 70 /** 71 * \brief Returns the codeword of the specified code type 72 * \see qpp::Codes::Type 73 * 74 * \param type Code type 75 * \param i Codeword index 76 * \return \a i-th codeword of the code \a type 77 */ codeword(Type type,idx i)78 static ket codeword(Type type, idx i) { 79 ket result; 80 switch (type) { 81 // [[5,1,3]] Five qubit code, as described in Nielsen and Chuang 82 case Type::FIVE_QUBIT: 83 switch (i) { 84 case 0: 85 result = 86 (mket({0, 0, 0, 0, 0}) + mket({1, 0, 0, 1, 0}) + 87 mket({0, 1, 0, 0, 1}) + mket({1, 0, 1, 0, 0}) + 88 mket({0, 1, 0, 1, 0}) - mket({1, 1, 0, 1, 1}) - 89 mket({0, 0, 1, 1, 0}) - mket({1, 1, 0, 0, 0}) - 90 mket({1, 1, 1, 0, 1}) - mket({0, 0, 0, 1, 1}) - 91 mket({1, 1, 1, 1, 0}) - mket({0, 1, 1, 1, 1}) - 92 mket({1, 0, 0, 0, 1}) - mket({0, 1, 1, 0, 0}) - 93 mket({1, 0, 1, 1, 1}) + mket({0, 0, 1, 0, 1})) / 94 4.; 95 break; 96 case 1: 97 result = 98 (mket({1, 1, 1, 1, 1}) + mket({0, 1, 1, 0, 1}) + 99 mket({1, 0, 1, 1, 0}) + mket({0, 1, 0, 1, 1}) + 100 mket({1, 0, 1, 0, 1}) - mket({0, 0, 1, 0, 0}) - 101 mket({1, 1, 0, 0, 1}) - mket({0, 0, 1, 1, 1}) - 102 mket({0, 0, 0, 1, 0}) - mket({1, 1, 1, 0, 0}) - 103 mket({0, 0, 0, 0, 1}) - mket({1, 0, 0, 0, 0}) - 104 mket({0, 1, 1, 1, 0}) - mket({1, 0, 0, 1, 1}) - 105 mket({0, 1, 0, 0, 0}) + mket({1, 1, 0, 1, 0})) / 106 4.; 107 break; 108 default: 109 throw exception::NoCodeword("qpp::Codes::codeword()"); 110 } 111 break; 112 // [[7,1,3]] Steane code, as described in Nielsen and Chuang 113 case Type::STEANE_SEVEN_QUBIT: 114 switch (i) { 115 case 0: 116 result = (mket({0, 0, 0, 0, 0, 0, 0}) + 117 mket({1, 0, 1, 0, 1, 0, 1}) + 118 mket({0, 1, 1, 0, 0, 1, 1}) + 119 mket({1, 1, 0, 0, 1, 1, 0}) + 120 mket({0, 0, 0, 1, 1, 1, 1}) + 121 mket({1, 0, 1, 1, 0, 1, 0}) + 122 mket({0, 1, 1, 1, 1, 0, 0}) + 123 mket({1, 1, 0, 1, 0, 0, 1})) / 124 std::sqrt(8.); 125 126 break; 127 case 1: 128 result = (mket({1, 1, 1, 1, 1, 1, 1}) + 129 mket({0, 1, 0, 1, 0, 1, 0}) + 130 mket({1, 0, 0, 1, 1, 0, 0}) + 131 mket({0, 0, 1, 1, 0, 0, 1}) + 132 mket({1, 1, 1, 0, 0, 0, 0}) + 133 mket({0, 1, 0, 0, 1, 0, 1}) + 134 mket({1, 0, 0, 0, 0, 1, 1}) + 135 mket({0, 0, 1, 0, 1, 1, 0})) / 136 std::sqrt(8.); 137 break; 138 default: 139 throw exception::NoCodeword("qpp::Codes::codeword()"); 140 } 141 break; 142 // [[9,1,3]] Shor code 143 case Type::SHOR_NINE_QUBIT: 144 ket shora = mket({0, 0, 0}) + mket({1, 1, 1}); 145 ket shorb = mket({0, 0, 0}) - mket({1, 1, 1}); 146 switch (i) { 147 case 0: 148 result = 149 kron(shora, kron(shora, shora)) / std::sqrt(8.); 150 break; 151 case 1: 152 result = 153 kron(shorb, kron(shorb, shorb)) / std::sqrt(8.); 154 break; 155 default: 156 throw exception::NoCodeword("qpp::Codes::codeword()"); 157 } 158 } 159 160 return result; 161 } 162 }; /* class Codes */ 163 164 } /* namespace qpp */ 165 166 #endif /* CLASSES_CODES_HPP_ */ 167