GCC Code Coverage Report


Directory: ./
File: Ops/include/Ops/Op.hpp
Date: 2022-10-15 05:10:18
Warnings: 1 unchecked decisions!
Exec Total Coverage
Lines: 4 26 15.4%
Functions: 3 19 15.8%
Branches: 1 26 3.8%
Decisions: 0 2 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 /**
18 * @file
19 * @brief Operations
20 */
21
22 #include <memory>
23 #include <optional>
24 #include <ostream>
25 #include <stdexcept>
26 #include <string>
27 #include <utility>
28 #include <vector>
29
30 #include "OpPtr.hpp"
31 #include "OpType/OpDesc.hpp"
32 #include "OpType/OpTypeFunctions.hpp"
33 #include "OpType/OpTypeInfo.hpp"
34 #include "Utils/Constants.hpp"
35 #include "Utils/Expression.hpp"
36 #include "Utils/Json.hpp"
37 #include "Utils/PauliStrings.hpp"
38 #include "Utils/UnitID.hpp"
39
40 namespace tket {
41
42 /** Wrong number of parameters for an operation */
43 class InvalidParameterCount : public std::logic_error {
44 public:
45 1 InvalidParameterCount()
46 1 : std::logic_error("Gate has an invalid number of parameters") {}
47 };
48
49 /**
50 * Abstract class representing an operation type
51 */
52 class Op : public std::enable_shared_from_this<Op> {
53 public:
54 /**
55 * Inverse (of a unitary operation)
56 *
57 * @throw BadOpType if operation is not unitary
58 */
59 virtual Op_ptr dagger() const { throw BadOpType(get_type()); }
60
61 /**
62 * Transpose of a unitary operation
63 */
64 virtual Op_ptr transpose() const { throw BadOpType(get_type()); };
65
66 /**
67 * Operation with values for symbols substituted
68 *
69 * @param sub_map map from symbols to values
70 *
71 * @return New operation with symbols substituted, or a null pointer if
72 * the operation type does not support symbols.
73 */
74 virtual Op_ptr symbol_substitution(
75 const SymEngine::map_basic_basic &sub_map) const = 0;
76
77 /** Sequence of phase parameters, if applicable */
78 virtual std::vector<Expr> get_params() const { throw BadOpType(get_type()); }
79
80 /** Sequence of phase parameters reduced to canonical range, if applicable */
81 virtual std::vector<Expr> get_params_reduced() const {
82 throw BadOpType(get_type());
83 }
84
85 /* Number of qubits */
86 virtual unsigned n_qubits() const { throw BadOpType(get_type()); }
87
88 /** String representation */
89 virtual std::string get_name(bool latex = false) const;
90
91 /** Command representation */
92 virtual std::string get_command_str(const unit_vector_t &args) const;
93
94 /** Get operation descriptor */
95 OpDesc get_desc() const { return desc_; }
96
97 /** Get operation type */
98 OpType get_type() const { return type_; }
99
100 /** Set of all free symbols occurring in operation parameters. */
101 virtual SymSet free_symbols() const = 0;
102
103 /**
104 * Which Pauli, if any, commutes with the operation at a given qubit
105 *
106 * @param i qubit number at which Pauli should commute
107 * @return A Pauli that commutes with the given operation
108 * @retval std::nullopt no Pauli commutes (or operation not a gate)
109 * @retval Pauli::I any Pauli commutes
110 */
111 virtual std::optional<Pauli> commuting_basis(unsigned i) const {
112 (void)i;
113 return std::nullopt;
114 }
115
116 /**
117 * Whether the operation commutes with the given Pauli at the given qubit
118 *
119 * @param colour Pauli operation type
120 * @param i operation qubit index
121 */
122 virtual bool commutes_with_basis(
123 const std::optional<Pauli> &colour, unsigned i) const {
124 (void)colour;
125 (void)i;
126 return false;
127 }
128
129 /**
130 * return if the op is external
131 */
132 virtual bool is_extern() const { return false; }
133
134 /** Vector specifying type of data for each port on op */
135 virtual op_signature_t get_signature() const = 0;
136
137 /**
138 * Test whether operation is identity up to a phase and return phase if so.
139 *
140 * @return phase, as multiple of pi, if operation is identity up to phase
141 * @throw BadOpType if operation is not a \ref Gate
142 */
143 virtual std::optional<double> is_identity() const {
144 throw BadOpType(get_type());
145 }
146
147 /**
148 * Test whether operation is in the Clifford group.
149 *
150 * A return value of true guarantees that the operation is Clifford. (Note
151 * that the converse is not the case: some Clifford operations may not be
152 * detected as such.)
153 *
154 * @retval true operation is in the Clifford group
155 */
156 virtual bool is_clifford() const { return false; }
157
158 /**
159 * If meaningful and implemented, return the numerical unitary matrix
160 * (in ILO-BE convention) which this Op represents.
161 *
162 * @pre No symbolic parameters.
163 * @return unitary matrix (ILO-BE) which this Op represents
164 * @throw BadOpType upon error.
165 */
166 virtual Eigen::MatrixXcd get_unitary() const { throw BadOpType(get_type()); }
167
168 virtual nlohmann::json serialize() const {
169
0/1
? Decision couldn't be analyzed.
throw JsonError("JSON serialization not yet implemented for " + get_name());
170 }
171
172 virtual ~Op() {}
173
174 bool operator==(const Op &other) const {
175 return type_ == other.type_ && is_equal(other);
176 }
177
178 /**
179 * Checks equality between two instances of the same class.
180 * The Op object passed as parameter must always be of the same type as this.
181 *
182 * For base class Op, it is sufficient that they have same type
183 */
184 1 virtual bool is_equal(const Op &) const { return true; }
185
186 protected:
187
1/2
✓ Branch 2 taken 2007993 times.
✗ Branch 3 not taken.
2007993 explicit Op(const OpType &type) : desc_(type), type_(type) {}
188 const OpDesc desc_; /**< Operation descriptor */
189 const OpType type_; /**< Operation type */
190 };
191
192 // friend to stream op (print)
193 std::ostream &operator<<(std::ostream &os, Op const &operation);
194
195 } // namespace tket
196