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 "Circuit/Circuit.hpp" |
18 |
|
|
|
|
19 |
|
|
|
namespace tket { |
20 |
|
|
|
|
21 |
|
|
|
typedef std::pair<Edge, Edge> edge_pair_t; |
22 |
|
|
|
|
23 |
|
|
|
// CycleCom stores minimum command information required for FrameRandomisation |
24 |
|
|
|
struct CycleCom { |
25 |
|
|
|
OpType type; |
26 |
|
|
|
std::vector<unsigned> indices; |
27 |
|
|
|
Vertex address; |
28 |
|
|
|
|
29 |
|
|
|
bool operator==(const CycleCom& other) const { |
30 |
|
|
|
return this->type == other.type && this->indices == other.indices; |
31 |
|
|
|
} |
32 |
|
|
|
}; |
33 |
|
|
|
|
34 |
|
|
|
// Cycle stores minimum subcircuit information requried for FrameRandomisation |
35 |
|
|
|
class Cycle { |
36 |
|
|
|
public: |
37 |
|
|
372 |
Cycle() {} |
38 |
|
|
✗ |
Cycle( |
39 |
|
|
|
const std::vector<edge_pair_t>& _boundary_edges, |
40 |
|
|
|
const std::vector<CycleCom>& _coms) |
41 |
|
|
✗ |
: boundary_edges_(_boundary_edges), coms_(_coms) {} |
42 |
|
|
|
|
43 |
|
|
|
// Returns size of boundary_edges_ |
44 |
|
|
|
unsigned size() const; |
45 |
|
|
|
|
46 |
|
|
|
// For edge_pair_t ep in boundary_edges_, if ep.first == source_edge, |
47 |
|
|
|
// ep.second = replacement_edge |
48 |
|
|
|
void update_boundary(const Edge& source_edge, const Edge& replacement_edge); |
49 |
|
|
|
|
50 |
|
|
|
// Adds coms_ from new_cycle to end of this->coms_ |
51 |
|
|
|
// Extends this->boundary_edges_ with new_cycles.boundary_edges_ |
52 |
|
|
|
void merge(Cycle& new_cycle); |
53 |
|
|
|
|
54 |
|
|
|
// if CycleCom.indices has unsigned equal to key in new_indices, change to |
55 |
|
|
|
// value |
56 |
|
|
|
void update_coms_indices(const std::map<unsigned, unsigned>& new_indices); |
57 |
|
|
|
|
58 |
|
|
|
// Cycle has noop vertices wired into edges in _boundary_edges for purpose of |
59 |
|
|
|
// Frame Randomisation This method these vertices in frame_vertices |
60 |
|
|
|
void add_vertex_pair(const std::pair<Vertex, Vertex>& verts); |
61 |
|
|
|
|
62 |
|
|
|
// Returns frame_vertices |
63 |
|
|
|
std::vector<std::pair<Vertex, Vertex>> get_frame() const; |
64 |
|
|
|
|
65 |
|
|
|
bool operator==(const Cycle& other) const { |
66 |
|
|
|
return this->size() == other.size() && this->coms_ == other.coms_; |
67 |
|
|
|
} |
68 |
|
|
|
|
69 |
|
|
|
std::vector<edge_pair_t> boundary_edges_; |
70 |
|
|
|
std::vector<CycleCom> coms_; |
71 |
|
|
|
|
72 |
|
|
|
private: |
73 |
|
|
|
std::vector<std::pair<Vertex, Vertex>> frame_vertices; |
74 |
|
|
|
}; |
75 |
|
|
|
|
76 |
|
|
|
// CycleHistory stores information used to find minimal number of boundaries |
77 |
|
|
|
struct CycleHistory { |
78 |
|
|
|
// Every time a new cycle is made it's assigned a key of type unsigned |
79 |
|
|
|
// The size of key is used to track the causal ordering of cycles |
80 |
|
|
|
unsigned key; |
81 |
|
|
|
// history.size() == key always |
82 |
|
|
|
// Tracks which UnitID were in which Cycle |
83 |
|
|
|
std::vector<std::vector<UnitID>> history; |
84 |
|
|
|
// Map from UnitID to key, where key maps in key_to_cycle to "active" Cycle |
85 |
|
|
|
std::map<UnitID, unsigned> uid_to_key; |
86 |
|
|
|
// Map from key to cycle, where a key n refers to the nth cycle made |
87 |
|
|
|
std::map<unsigned, Cycle> key_to_cycle; |
88 |
|
|
|
}; |
89 |
|
|
|
|
90 |
|
|
|
class CycleFinder { |
91 |
|
|
|
public: |
92 |
|
|
19 |
CycleFinder(const Circuit& _circ, const OpTypeSet& _cycle_types) |
93 |
|
|
19 |
: circ(_circ), cycle_types_(_cycle_types){}; |
94 |
|
|
|
|
95 |
|
|
|
// Cycles are sub-circuits of circ where every gate has OpType in cycle_types_ |
96 |
|
|
|
// get_cycles() returns the minimum number of cycles such that every |
97 |
|
|
|
// cycle_types_ gate in circ is in one cycle |
98 |
|
|
|
std::vector<Cycle> get_cycles(); |
99 |
|
|
|
|
100 |
|
|
|
private: |
101 |
|
|
|
// Circuit cycles are found in |
102 |
|
|
|
const Circuit& circ; |
103 |
|
|
|
// OpType cycle gates have |
104 |
|
|
|
const OpTypeSet cycle_types_; |
105 |
|
|
|
|
106 |
|
|
|
// CycleFinder uses SliceIterator to find get circ gates in cycle_types_ |
107 |
|
|
|
// In Edges to a new slice are checked for equality with the last boundary out |
108 |
|
|
|
// edge stored for their UnitID If equal a cycle may be extended, if not equal |
109 |
|
|
|
std::map<Edge, UnitID> cycle_out_edges; |
110 |
|
|
|
|
111 |
|
|
|
// Stores data structures for tracking created Cycles and associated UnitID's |
112 |
|
|
|
CycleHistory bt; |
113 |
|
|
|
|
114 |
|
|
|
// Given a new CutFrontier object, creates new cycles from interior vertices |
115 |
|
|
|
// and merges them with previous cycles where possible |
116 |
|
|
|
void extend_cycles(const CutFrontier& cut); |
117 |
|
|
|
|
118 |
|
|
|
// Makes a new Cycle object from given dag information |
119 |
|
|
|
// Return type used to identify whether cycle should be merged with previous |
120 |
|
|
|
// cycles |
121 |
|
|
|
std::pair<unsigned, std::set<unsigned>> make_cycle( |
122 |
|
|
|
const Vertex& v, const EdgeVec& out_edges, const CutFrontier& cut); |
123 |
|
|
|
|
124 |
|
|
|
// Uses CycleHistory to merge Cycle attributed to new_key with Cycles |
125 |
|
|
|
// attributed to old_keys Cycles are merged in to Cycle with smallest key |
126 |
|
|
|
void merge_cycles(unsigned new_key, std::set<unsigned>& old_keys); |
127 |
|
|
|
|
128 |
|
|
|
// Updates cycle_out_edges with new Edge |
129 |
|
|
|
// UnitID should not be new, so error thrown if not found |
130 |
|
|
|
void update_cycle_out_edges(const UnitID& uid, const Edge& e); |
131 |
|
|
|
|
132 |
|
|
|
// Getter for UnitID from unit_frontier_t in Cut |
133 |
|
|
|
UnitID unitid_from_unit_frontier( |
134 |
|
|
|
const std::shared_ptr<unit_frontier_t>& u_frontier, const Edge& e) const; |
135 |
|
|
|
|
136 |
|
|
|
// if unsigned in erase_from is <= to_erase, removes from erase_from |
137 |
|
|
|
void erase_keys( |
138 |
|
|
|
const unsigned& to_erase, std::set<unsigned>& erase_from) const; |
139 |
|
|
|
|
140 |
|
|
|
// removes unsigned from old_keys that have cycles that can't merge with |
141 |
|
|
|
// new_key adds new_key to old_keys |
142 |
|
|
|
void order_keys(unsigned& new_key, std::set<unsigned>& old_keys) const; |
143 |
|
|
|
}; |
144 |
|
|
|
} // namespace tket |
145 |
|
|
|
|