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 | #include "Circuit/Boxes.hpp" | |||
17 | #include "Circuit/CircUtils.hpp" | |||
18 | #include "Circuit/Circuit.hpp" | |||
19 | #include "Utils/HelperFunctions.hpp" | |||
20 | #include "Utils/Json.hpp" | |||
21 | #include "Utils/MatrixAnalysis.hpp" | |||
22 | namespace tket { | |||
23 | ||||
24 | /** | |||
25 | * PhasePolynomial is just a sequence of parities: that is, terms of the form | |||
26 | * \f$ e^{\alpha \bigotimes Z} \f$, where Z is a Pauli Z. This is capable of | |||
27 | * representing a restricted set of circuits made up of CNOTs and Rzs: | |||
28 | * specifically, circuits where the output qubits have the same state as the | |||
29 | * inputs, modulo (local) phases. The vectors are always assumed to be the same | |||
30 | * size as the qubit count. */ | |||
31 | typedef std::map<std::vector<bool>, Expr> PhasePolynomial; | |||
32 | typedef std::pair<std::vector<bool>, Expr> phase_term_t; | |||
33 | ||||
34 | /* arXiv:1712.01859 : heuristic for synthesis of phase polynomial into | |||
35 | a CNOT-dihedral circuit (ie CNOT + Rz). Architecture-blind. */ | |||
36 | Circuit gray_synth( | |||
37 | unsigned n_qubits, const std::list<phase_term_t> &parities, | |||
38 | const MatrixXb &linear_transformation); | |||
39 | ||||
40 | /** | |||
41 | * A PhasePolyBox is capable of representing arbitrary Circuits made up of CNOT | |||
42 | * and RZ, as a PhasePolynomial plus a boolean matrix representing an additional | |||
43 | * linear transformation. | |||
44 | */ | |||
45 | class PhasePolyBox : public Box { | |||
46 | public: | |||
47 | explicit PhasePolyBox(const Circuit &circ); | |||
48 | explicit PhasePolyBox( | |||
49 | unsigned n_qubits, const boost::bimap<Qubit, unsigned> &qubit_indices, | |||
50 | const PhasePolynomial &phase_polynomial, | |||
51 | const MatrixXb &linear_transformation); | |||
52 | ||||
53 | PhasePolyBox() : Box(OpType::PhasePolyBox) {} | |||
54 | ||||
55 | /** | |||
56 | * Copy constructor | |||
57 | */ | |||
58 | PhasePolyBox(const PhasePolyBox &other); | |||
59 | ||||
60 | ✗ | ~PhasePolyBox() override {} | ||
61 | ||||
62 | Op_ptr symbol_substitution( | |||
63 | const SymEngine::map_basic_basic &sub_map) const override; | |||
64 | ||||
65 | SymSet free_symbols() const override; | |||
66 | ||||
67 | 9 | bool is_equal(const Op &op_other) const override { | ||
68 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | const PhasePolyBox &other = dynamic_cast<const PhasePolyBox &>(op_other); | |
69 | return ( | |||
70 | 18 | this->n_qubits_ == other.n_qubits_ && | ||
71 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | this->phase_polynomial_ == other.phase_polynomial_ && | |
72 |
3/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 1 times.
|
26 | this->linear_transformation_ == other.linear_transformation_ && | |
73 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
17 | this->qubit_indices_ == other.qubit_indices_); | |
74 | } | |||
75 | ||||
76 | ✗ | const PhasePolynomial &get_phase_polynomial() const { | ||
77 | ✗ | return phase_polynomial_; | ||
78 | } | |||
79 | ✗ | const MatrixXb &get_linear_transformation() const { | ||
80 | ✗ | return linear_transformation_; | ||
81 | } | |||
82 | 1 | const boost::bimap<Qubit, unsigned> &get_qubit_indices() const { | ||
83 | 1 | return qubit_indices_; | ||
84 | } | |||
85 | ||||
86 | 98 | unsigned get_n_qubits() const { return n_qubits_; } | ||
87 | ||||
88 | static Op_ptr from_json(const nlohmann::json &j); | |||
89 | ||||
90 | static nlohmann::json to_json(const Op_ptr &op); | |||
91 | ||||
92 | protected: | |||
93 | // automatically uses GraySynth | |||
94 | // (https://arxiv.org/pdf/1712.01859.pdf) | |||
95 | // other circuit generation methods (for architectures) to come! | |||
96 | void generate_circuit() const override; | |||
97 | ||||
98 | private: | |||
99 | unsigned n_qubits_; | |||
100 | boost::bimap<Qubit, unsigned> qubit_indices_; | |||
101 | PhasePolynomial phase_polynomial_; | |||
102 | MatrixXb linear_transformation_; | |||
103 | }; | |||
104 | ||||
105 | /** | |||
106 | * this class realises the conversion all sub circuits of a given circuits which | |||
107 | * contains only CX+Rz to a PhasePolyBox. The circuit should contain only | |||
108 | * CX, Rz, H, measure, reset, collape, barrier. | |||
109 | */ | |||
110 | class CircToPhasePolyConversion { | |||
111 | public: | |||
112 | /** | |||
113 | * converts all sub circuits of a given circuits which contains only | |||
114 | * CX+Rz to a PhasePolyBox. | |||
115 | * @throw not implemented for unsupported gates | |||
116 | * @param circ circuit to be converted | |||
117 | * @param min_size value for the minimal number of CX in each box, groups with | |||
118 | * less than min_size CX gates are not converted to a PhasePolyBox, default | |||
119 | * value is 0 | |||
120 | */ | |||
121 | explicit CircToPhasePolyConversion( | |||
122 | const Circuit &circ, unsigned min_size = 0); | |||
123 | void convert(); | |||
124 | Circuit get_circuit() const; | |||
125 | ||||
126 | private: | |||
127 | enum class QubitType { pre, in, post }; | |||
128 | void add_phase_poly_box(); | |||
129 | unsigned nq_; | |||
130 | unsigned nb_; | |||
131 | unsigned min_size_; | |||
132 | unsigned box_size_; | |||
133 | std::map<Qubit, unsigned> qubit_indices_; | |||
134 | std::map<Bit, unsigned> bit_indices_; | |||
135 | std::vector<QubitType> qubit_types_; | |||
136 | qubit_vector_t all_qu_; | |||
137 | Circuit input_circ_; | |||
138 | Circuit box_circ_; | |||
139 | Circuit post_circ_; | |||
140 | Circuit circ_; | |||
141 | Circuit empty_circ_; | |||
142 | }; | |||
143 | ||||
144 | } // namespace tket | |||
145 |