GCC Code Coverage Report


Directory: ./
File: Clifford/include/Clifford/UnitaryTableau.hpp
Date: 2022-10-15 05:10:18
Exec Total Coverage
Lines: 1 1 100.0%
Functions: 1 1 100.0%
Branches: 1 2 50.0%
Decisions: 0 0 -%

Line Branch Decision Exec Source
1 // Copyright 2019-2022 Cambridge Quantum Computing
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #pragma once
16
17 #include "SymplecticTableau.hpp"
18
19 namespace tket {
20
21 // Forward declare Circuit for friend converter
22 class Circuit;
23
24 class UnitaryTableau {
25 /**
26 * An implementation of the stabilizer-destabilizer tableau for unitary
27 * Cliffords in Aaronson & Gottesman, "Improved Simulation of Stabilizer
28 * Circuits", https://arxiv.org/pdf/quant-ph/0406196.pdf
29 *
30 * If a Pauli is placed at an input before the unitary, there is a Pauli
31 * string over the outputs which would have an equivalent effect. The rows
32 * correspond to these Pauli strings for X and Z on each input qubit. In other
33 * terms, the ith X row is the (phaseful) Pauli string P such that P C X_i =
34 * C, and similarly for the Z rows.
35 *
36 * The Z rows generate the stabilizer group for the state prepared when the
37 * unitary is applied to the initial |0>^n state, with the X rows extending
38 * this to generate the full n-fold Pauli group.
39 *
40 * Qubits indexed using Qubit objects.
41 */
42 public:
43 /**
44 * Construct the tableau for the identity over n qubits (given default qubit
45 * names).
46 */
47 explicit UnitaryTableau(unsigned n);
48
49 /**
50 * Construct the tableau for the identity over specific qubits.
51 */
52 explicit UnitaryTableau(const qubit_vector_t& qbs);
53
54 /**
55 * Construct a tableau from the underlying binary matrices.
56 * Qubits given default names.
57 * @param xx The X component of the X rows
58 * @param xz The Z component of the X rows
59 * @param xph The phases of the X rows
60 * @param zx The X component of the Z rows
61 * @param zz The Z component of the Z rows
62 * @param zph The phases of the Z rows
63 */
64 explicit UnitaryTableau(
65 const MatrixXb& xx, const MatrixXb& xz, const VectorXb& xph,
66 const MatrixXb& zx, const MatrixXb& zz, const VectorXb& zph);
67
68 /**
69 * Other required constructors
70 */
71
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 UnitaryTableau(const UnitaryTableau& other) = default;
72 UnitaryTableau(UnitaryTableau&& other) = default;
73 UnitaryTableau& operator=(const UnitaryTableau& other) = default;
74 UnitaryTableau& operator=(UnitaryTableau&& other) = default;
75
76 /**
77 * Read off an X row as a Pauli string
78 */
79 QubitPauliTensor get_xrow(const Qubit& qb) const;
80
81 /**
82 * Read off a Z row as a Pauli string
83 */
84 QubitPauliTensor get_zrow(const Qubit& qb) const;
85
86 /**
87 * Combine rows into a single row according to a QubitPauliTensor
88 */
89 QubitPauliTensor get_row_product(const QubitPauliTensor& qpt) const;
90
91 /**
92 * Access all IDs for the qubits used in the tableau.
93 */
94 std::set<Qubit> get_qubits() const;
95
96 /**
97 * Transform the tableau according to consuming a Clifford gate at either end
98 * of the circuit.
99 */
100 void apply_S_at_front(const Qubit& qb);
101 void apply_S_at_end(const Qubit& qb);
102 void apply_V_at_front(const Qubit& qb);
103 void apply_V_at_end(const Qubit& qb);
104 void apply_CX_at_front(const Qubit& control, const Qubit& target);
105 void apply_CX_at_end(const Qubit& control, const Qubit& target);
106 void apply_gate_at_front(OpType type, const qubit_vector_t& qbs);
107 void apply_gate_at_end(OpType type, const qubit_vector_t& qbs);
108
109 /**
110 * Transform the tableau according to consuming a Clifford-phase Pauli gadget
111 * at either end of the circuit.
112 *
113 * @param pauli The string of the Pauli gadget
114 * @param half_pis The Clifford angle: {0, 1, 2, 3} represents {0, pi/2, pi,
115 * -pi/2}
116 */
117 void apply_pauli_at_front(const QubitPauliTensor& pauli, unsigned half_pis);
118 void apply_pauli_at_end(const QubitPauliTensor& pauli, unsigned half_pis);
119
120 /**
121 * Combine two tableaux in sequence.
122 * Will throw an exception if the tableaux are not over the same set of
123 * qubits.
124 *
125 * @param first first circuit
126 * @param second second circuit
127 *
128 * @return The tableau corresponding to applying \p first, followed by \p
129 * second
130 */
131 static UnitaryTableau compose(
132 const UnitaryTableau& first, const UnitaryTableau& second);
133
134 /**
135 * Gives the UnitaryTableau corresponding to the inverse (dagger) or transpose
136 * unitary. This is distinct from simply transposing the binary matrix
137 * representation. Takes time O(N^3) for N qubits.
138 */
139 UnitaryTableau dagger() const;
140 UnitaryTableau transpose() const;
141
142 /**
143 * Gives the UnitaryTableau corresponding to the complex conjugate unitary.
144 * This calls conjugate() on the underlying SymplecticTableau.
145 */
146 UnitaryTableau conjugate() const;
147
148 friend UnitaryTableau circuit_to_unitary_tableau(const Circuit& circ);
149 friend Circuit unitary_tableau_to_circuit(const UnitaryTableau& tab);
150
151 friend void to_json(nlohmann::json& j, const UnitaryTableau& tab);
152 friend void from_json(const nlohmann::json& j, UnitaryTableau& tab);
153
154 friend std::ostream& operator<<(std::ostream& os, const UnitaryTableau& tab);
155 bool operator==(const UnitaryTableau& other) const;
156
157 private:
158 /**
159 * The actual binary tableau.
160 * Rows 0-(n-1) are the X rows, n-(2n-1) are the Z rows.
161 */
162 SymplecticTableau tab_;
163
164 /** Map from qubit IDs to their row/column index in tableau */
165 boost::bimap<Qubit, unsigned> qubits_;
166 };
167
168 JSON_DECL(UnitaryTableau)
169
170 std::ostream& operator<<(std::ostream& os, const UnitaryTableau& tab);
171
172 } // namespace tket
173