tket
Loading...
Searching...
No Matches
GreedyPauliOptimisation.hpp
Go to the documentation of this file.
1// Copyright Quantinuum
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 <atomic>
18
19#include "Transform.hpp"
22
23namespace tket {
24
25namespace Transforms {
26
27namespace GreedyPauliSimp {
28
29class GreedyPauliSimpError : public std::logic_error {
30 public:
31 explicit GreedyPauliSimpError(const std::string& message)
32 : std::logic_error(message) {}
33};
34
39enum class TQEType : unsigned {
40 XX = 0,
41 XY,
42 XZ,
43 YX,
44 YY,
45 YZ,
46 ZX,
47 ZY,
48 ZZ,
49};
50
51enum class PauliNodeType {
52 // Pauli rotation
54 // Defines how a Pauli X and a Pauli Z on the same qubit
55 // get propagated from right to left through a Clifford operator.
57 // Conditional Pauli rotations
59 // Classical operation
61 // Mid-circuit measurement
63 // Reset
64 Reset,
65};
66
72enum class CommuteType : unsigned {
73 // Both are (I)dentity
74 I,
75 // (A)nti-commute
76 A,
77 // (C)ommute and not both identity
78 C,
79};
80
81enum class BitType : unsigned {
82 READ,
83 WRITE,
84};
85
90struct TQE {
92 unsigned a;
93 unsigned b;
94 bool operator<(const TQE& other) const {
95 return std::tie(type, a, b) < std::tie(other.type, other.a, other.b);
96 }
97};
98
106 unsigned a;
107 unsigned b;
109 unsigned index;
110 bool operator<(const Rotation2Q& other) const { return index < other.index; }
111};
112
118 std::vector<std::vector<Pauli>> paulis;
119 // We use UnitID to differentiate between Bit and WasmState
120 std::vector<std::pair<UnitID, BitType>> bits_info;
121};
122
128 public:
129 virtual PauliNodeType get_type() const = 0;
130 virtual unsigned tqe_cost() const = 0;
131 virtual int tqe_cost_increase(const TQE& tqe) const = 0;
132 virtual void update(const TQE& tqe) = 0;
133 virtual void update(const OpType& sq_cliff, const unsigned& a);
134 virtual void swap(const unsigned& a, const unsigned& b);
135 virtual CommuteInfo get_commute_info() const = 0;
136 virtual std::vector<TQE> reduction_tqes() const = 0;
137 virtual ~PauliNode();
138};
139
140typedef std::shared_ptr<PauliNode> PauliNode_ptr;
141
145class SingleNode : public PauliNode {
146 public:
153 SingleNode(std::vector<Pauli> string, bool sign);
154
160 unsigned tqe_cost() const override;
161
168 int tqe_cost_increase(const TQE& tqe) const override;
169
175 void update(const TQE& tqe) override;
176
182 std::vector<TQE> reduction_tqes() const override;
183
189 std::pair<unsigned, Pauli> first_support() const;
190
191 bool sign() const { return sign_; };
192
193 const std::vector<Pauli>& string() const { return string_; };
194
195 protected:
196 std::vector<Pauli> string_;
197 bool sign_;
198 // extra cached data used by greedy synthesis
199 unsigned weight_;
200};
201
205class ACPairNode : public PauliNode {
206 public:
216 std::vector<Pauli> z_string, std::vector<Pauli> x_string, bool z_sign,
217 bool x_sign);
218
224 unsigned tqe_cost() const override;
225
233 int tqe_cost_increase(const TQE& tqe) const override;
234
240 void update(const TQE& tqe) override;
241
248 void update(const OpType& sq_cliff, const unsigned& a) override;
249
256 void swap(const unsigned& a, const unsigned& b) override;
257
263 std::vector<TQE> reduction_tqes() const override;
264
268 std::tuple<unsigned, Pauli, Pauli> first_support() const;
269
270 bool z_sign() const { return z_sign_; };
271
272 bool x_sign() const { return x_sign_; };
273
274 const std::vector<Pauli>& z_string() const { return z_string_; };
275
276 const std::vector<Pauli>& x_string() const { return x_string_; };
277
278 protected:
279 std::vector<Pauli> z_string_;
280 std::vector<Pauli> x_string_;
283 // extra cached data used by greedy synthesis
284 std::vector<CommuteType> commute_type_vec_;
287};
288
292class ClassicalNode : public PauliNode {
293 public:
294 ClassicalNode(std::vector<UnitID> args, Op_ptr op);
295
296 PauliNodeType get_type() const override {
298 };
299
300 unsigned tqe_cost() const override { return 0; };
301 int tqe_cost_increase(const TQE& /*tqe*/) const override { return 0; };
302 void update(const TQE& /*tqe*/) override { return; };
303 std::vector<TQE> reduction_tqes() const override { return {}; };
304 std::vector<UnitID> args() const { return args_; };
305 Op_ptr op() const { return op_; };
306
307 CommuteInfo get_commute_info() const override;
308
309 protected:
310 const std::vector<UnitID> args_;
311 const Op_ptr op_;
312};
313
318class PauliRotation : public SingleNode {
319 public:
327 PauliRotation(std::vector<Pauli> string, bool sign, Expr theta);
328
329 PauliNodeType get_type() const override {
331 };
332
333 Expr angle() const { return sign_ ? theta_ : -theta_; };
334
335 CommuteInfo get_commute_info() const override;
336
337 protected:
339};
340
344class MidMeasure : public SingleNode {
345 public:
353 MidMeasure(std::vector<Pauli> string, bool sign, unsigned bit);
354
356 CommuteInfo get_commute_info() const override;
357 unsigned bit() const { return bit_; };
358
359 protected:
360 const unsigned bit_;
361};
362
367 public:
376 std::vector<std::tuple<std::vector<Pauli>, bool, Expr>> rotations,
377 std::vector<unsigned> cond_bits, unsigned cond_value);
378
384 unsigned tqe_cost() const override;
385
393 int tqe_cost_increase(const TQE& tqe) const override;
394
400 void update(const TQE& tqe) override;
401
402 std::vector<TQE> reduction_tqes() const override { return {}; };
403
404 std::vector<unsigned> cond_bits() const { return cond_bits_; };
405 unsigned cond_value() const { return cond_value_; };
406
407 PauliNodeType get_type() const override {
409 };
410
411 CommuteInfo get_commute_info() const override;
412
413 void append(const ConditionalBlock& other);
414
415 const std::vector<std::tuple<std::vector<Pauli>, bool, Expr>>& rotations()
416 const {
417 return rotations_;
418 };
419
420 protected:
421 std::vector<std::tuple<std::vector<Pauli>, bool, Expr>> rotations_;
422 const std::vector<unsigned> cond_bits_;
423 const unsigned cond_value_;
424 // extra cached data used by greedy synthesis
426};
427
436 public:
447 std::vector<Pauli> z_string, std::vector<Pauli> x_string, bool z_sign,
448 bool x_sign, unsigned qubit_index);
449
450 PauliNodeType get_type() const override {
452 };
453
454 CommuteInfo get_commute_info() const override;
455
456 unsigned qubit_index() const { return qubit_index_; };
457
458 private:
459 const unsigned qubit_index_;
460};
461
469class Reset : public ACPairNode {
470 public:
479 Reset(
480 std::vector<Pauli> z_string, std::vector<Pauli> x_string, bool z_sign,
481 bool x_sign);
482
483 PauliNodeType get_type() const override { return PauliNodeType::Reset; };
484 CommuteInfo get_commute_info() const override;
485};
486
487typedef boost::adjacency_list<
488 boost::listS, boost::listS, boost::bidirectionalS,
489 // indexing needed for algorithms such as topological sort
490 boost::property<boost::vertex_index_t, int, PauliNode_ptr>>
492
493typedef boost::graph_traits<GPDAG>::vertex_descriptor GPVert;
494typedef boost::graph_traits<GPDAG>::edge_descriptor GPEdge;
495
498
499typedef boost::adj_list_vertex_property_map<
500 GPDAG, int, int&, boost::vertex_index_t>
502
526class GPGraph {
527 public:
529 GPGraph(qubit_vector_t qubits, bit_vector_t bits);
530
531 GPVertSet get_successors(const GPVert& vert) const;
532
533 GPVertSet get_predecessors(const GPVert& vert) const;
534
542 std::vector<GPVert> vertices_in_order() const;
543
544 std::tuple<
545 std::vector<std::vector<PauliNode_ptr>>, std::vector<PauliNode_ptr>,
546 boost::bimap<unsigned, unsigned>>
547 get_sequence(std::shared_ptr<std::atomic<bool>> stop_flag);
548
557 const Command& cmd, bool conditional = false,
558 std::vector<unsigned> cond_bits = {}, unsigned cond_value = 0);
559
560 private:
566 void apply_paulis_at_end(
567 const std::vector<std::pair<std::vector<Pauli>, Expr>>& rotations,
568 const qubit_vector_t& qbs, bool conditional = false,
569 std::vector<unsigned> cond_bits = {}, unsigned cond_value = 0);
570
574 void apply_node_at_end(PauliNode_ptr& node);
575
582 mutable GPDAG graph_;
583 const unsigned n_qubits_;
584 const unsigned n_bits_;
585
587 UnitaryRevTableau cliff_;
589 boost::bimap<unsigned, unsigned> end_measures_;
590
591 GPVertSet start_line_;
592 GPVertSet end_line_;
593};
594
602std::tuple<std::vector<PauliNode_ptr>, std::vector<PauliNode_ptr>>
603gpg_from_unordered_set(const std::vector<SymPauliTensor>& unordered_set);
604
623 const Circuit& circ, std::atomic<bool>& stop_flag,
624 double discount_rate = 0.7, double depth_weight = 0.3,
625 unsigned max_lookahead = 500, unsigned max_tqe_candidates = 500,
626 unsigned seed = 0, bool allow_zzphase = false);
627
644 const Circuit& circ, double discount_rate = 0.7, double depth_weight = 0.3,
645 unsigned max_lookahead = 500, unsigned max_tqe_candidates = 500,
646 unsigned seed = 0, bool allow_zzphase = false);
647
662 const std::vector<SymPauliTensor>& unordered_set, double depth_weight = 0.3,
663 unsigned max_lookahead = 500, unsigned max_tqe_candidates = 500,
664 unsigned seed = 0, bool allow_zzphase = false);
665
666} // namespace GreedyPauliSimp
667
669 double discount_rate = 0.7, double depth_weight = 0.3,
670 unsigned max_lookahead = 500, unsigned max_tqe_candidates = 500,
671 unsigned seed = 0, bool allow_zzphase = false,
672 unsigned thread_timeout = 100, unsigned trials = 1);
673
674} // namespace Transforms
675
676} // namespace tket
A circuit.
Definition Circuit.hpp:212
A transformation of a circuit that preserves its semantics.
Definition Transform.hpp:27
Base class for nodes defined by a pair of anti-commuting Pauli strings.
int tqe_cost_increase(const TQE &tqe) const override
Number of additional TQEs would required to reduce the weight to 1 after the given TQE is applied.
std::vector< TQE > reduction_tqes() const override
Return all possible TQE gates that will reduce the tqe cost.
void swap(const unsigned &a, const unsigned &b) override
Update the support vector with a SWAP gate.
std::tuple< unsigned, Pauli, Pauli > first_support() const
Return the index and value of the first anti-commute entry.
void update(const TQE &tqe) override
Update the support vector with a TQE gate.
unsigned tqe_cost() const override
Number of TQEs required to reduce the weight to 1.
std::vector< std::tuple< std::vector< Pauli >, bool, Expr > > rotations_
const std::vector< std::tuple< std::vector< Pauli >, bool, Expr > > & rotations() const
void update(const TQE &tqe) override
Update the all Pauli rotations with the given TQE.
unsigned tqe_cost() const override
Sum of tqe_cost for each Pauli rotation.
int tqe_cost_increase(const TQE &tqe) const override
Sum of tqe_cost for each Pauli rotation after the given TQE is applied.
Pauli graph structure for GreedyPauliSimp.
std::vector< GPVert > vertices_in_order() const
All vertices of the DAG, topologically sorted.
GPVertSet get_successors(const GPVert &vert) const
void apply_gate_at_end(const Command &cmd, bool conditional=false, std::vector< unsigned > cond_bits={}, unsigned cond_value=0)
Applies the given gate to the end of the graph.
GPVertSet get_predecessors(const GPVert &vert) const
std::tuple< std::vector< std::vector< PauliNode_ptr > >, std::vector< PauliNode_ptr >, boost::bimap< unsigned, unsigned > > get_sequence(std::shared_ptr< std::atomic< bool > > stop_flag)
Measurement that has quantum or classical successors.
Base class for nodes in the Greedy Pauli graph.
virtual void update(const TQE &tqe)=0
virtual PauliNodeType get_type() const =0
virtual CommuteInfo get_commute_info() const =0
virtual unsigned tqe_cost() const =0
virtual void swap(const unsigned &a, const unsigned &b)
virtual std::vector< TQE > reduction_tqes() const =0
virtual int tqe_cost_increase(const TQE &tqe) const =0
Defines how a Pauli X and a Pauli Z on the same qubit get propagated from right to left through a Cli...
A Pauli exponential defined by a dense Pauli string and a rotation angle.
Reset operation defined by a pair of anti-commuting strings For example, a tket Reset OpType can be d...
CommuteInfo get_commute_info() const override
Base class for nodes defined by a single Pauli string.
int tqe_cost_increase(const TQE &tqe) const override
Number of TQEs would required to reduce the weight to 1 after the given TQE is applied.
std::vector< TQE > reduction_tqes() const override
Return all possible TQE gates that will reduce the tqe cost by 1.
void update(const TQE &tqe) override
Update the Pauli string with a TQE gate.
std::pair< unsigned, Pauli > first_support() const
Return the index and value of the first non-identity.
unsigned tqe_cost() const override
Number of TQEs required to reduce the weight to 1.
STL namespace.
Circuit greedy_pauli_set_synthesis(const std::vector< SymPauliTensor > &unordered_set, double depth_weight, unsigned max_lookahead, unsigned max_tqe_candidates, unsigned seed, bool allow_zzphase)
Synthesise a set of unordered Pauli exponentials by applying Clifford gates and single qubit rotation...
Circuit greedy_pauli_graph_synthesis(const Circuit &circ, double discount_rate, double depth_weight, unsigned max_lookahead, unsigned max_tqe_candidates, unsigned seed, bool allow_zzphase)
Converts the given circuit into a GPGraph and conjugates each node by greedily applying 2-qubit Cliff...
boost::graph_traits< GPDAG >::vertex_descriptor GPVert
TQEType
Types of 2-qubit entangled Clifford gates.
CommuteType
The type of a pair of Pauli letters defined by their commutation relation.
boost::graph_traits< GPDAG >::edge_descriptor GPEdge
std::tuple< std::vector< PauliNode_ptr >, std::vector< PauliNode_ptr > > gpg_from_unordered_set(const std::vector< SymPauliTensor > &unordered_set)
Convert a unordered set of SymPauliTensor into a set of PauliRotations followed by a set of PauliProp...
boost::adjacency_list< boost::listS, boost::listS, boost::bidirectionalS, boost::property< boost::vertex_index_t, int, PauliNode_ptr > > GPDAG
std::shared_ptr< PauliNode > PauliNode_ptr
boost::adj_list_vertex_property_map< GPDAG, int, int &, boost::vertex_index_t > GPVIndex
Circuit greedy_pauli_graph_synthesis_flag(const Circuit &circ, std::shared_ptr< std::atomic< bool > > stop_flag, double discount_rate, double depth_weight, unsigned max_lookahead, unsigned max_tqe_candidates, unsigned seed, bool allow_zzphase)
Transform greedy_pauli_optimisation(double discount_rate, double depth_weight, unsigned max_lookahead, unsigned max_tqe_candidates, unsigned seed, bool allow_zzphase, unsigned thread_timeout, unsigned trials)
Defines tket::DeviceCharacterisation, used in NoiseAwarePlacement and in commute_SQ_gates_through_SWA...
Definition Path.cpp:22
OpType
Named operation types.
Definition OpType.hpp:29
Pauli
Symbols for the Pauli operators (and identity)
boost::multi_index::multi_index_container< T, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< TagKey >, boost::multi_index::identity< T > >, boost::multi_index::sequenced< boost::multi_index::tag< TagSeq > > > > sequence_set_t
SymEngine::Expression Expr
Representation of a phase as a multiple of .
std::shared_ptr< const Op > Op_ptr
Definition OpPtr.hpp:24
std::vector< Bit > bit_vector_t
Definition UnitID.hpp:319
std::vector< Qubit > qubit_vector_t
Definition UnitID.hpp:315
Commutation information of a node specified by a list of Pauli strings along with classical READs and...
std::vector< std::pair< UnitID, BitType > > bits_info
Struct for 2-qubit entangled Clifford gates.