@@ -53,35 +53,14 @@ bool CircuitSeq::fully_equivalent(const CircuitSeq &other) const {
53
53
}
54
54
std::unordered_map<CircuitWire *, CircuitWire *> wires_mapping;
55
55
for (int i = 0 ; i < (int )wires.size (); i++) {
56
- wires_mapping[other. wires [i].get ()] = wires[i].get ();
56
+ wires_mapping[wires[i].get ()] = other. wires [i].get ();
57
57
}
58
58
for (int i = 0 ; i < (int )gates.size (); i++) {
59
- if (gates[i]->gate ->tp != other.gates [i]->gate ->tp ) {
60
- return false ;
61
- }
62
- if (gates[i]->input_wires .size () != other.gates [i]->input_wires .size () ||
63
- gates[i]->output_wires .size () != other.gates [i]->output_wires .size ()) {
59
+ if (!CircuitGate::equivalent (gates[i].get (), other.gates [i].get (),
60
+ wires_mapping,
61
+ /* update_mapping=*/ false , nullptr )) {
64
62
return false ;
65
63
}
66
- for (int j = 0 ; j < (int )gates[i]->input_wires .size (); j++) {
67
- if (other.gates [i]->input_wires [j]->is_qubit ()) {
68
- if (wires_mapping[other.gates [i]->input_wires [j]] !=
69
- gates[i]->input_wires [j]) {
70
- return false ;
71
- }
72
- } else {
73
- // parameters should not be mapped
74
- if (other.gates [i]->input_wires [j] != gates[i]->input_wires [j]) {
75
- return false ;
76
- }
77
- }
78
- }
79
- for (int j = 0 ; j < (int )gates[i]->output_wires .size (); j++) {
80
- if (wires_mapping[other.gates [i]->output_wires [j]] !=
81
- gates[i]->output_wires [j]) {
82
- return false ;
83
- }
84
- }
85
64
}
86
65
return true ;
87
66
}
@@ -123,35 +102,11 @@ bool CircuitSeq::topologically_equivalent(const CircuitSeq &other) const {
123
102
if (!--gate_remaining_in_degree[this_gate]) {
124
103
// Check if this gate is the same as the other gate
125
104
auto other_gate = other_wire->output_gates [i];
126
- if (this_gate->gate ->tp != other_gate->gate ->tp ) {
105
+ if (!CircuitGate::equivalent (this_gate, other_gate, wires_mapping,
106
+ /* update_mapping=*/ true ,
107
+ &wires_to_search)) {
127
108
return false ;
128
109
}
129
- if (this_gate->input_wires .size () != other_gate->input_wires .size () ||
130
- this_gate->output_wires .size () != other_gate->output_wires .size ()) {
131
- return false ;
132
- }
133
- for (int j = 0 ; j < (int )this_gate->input_wires .size (); j++) {
134
- if (this_gate->input_wires [j]->is_qubit ()) {
135
- // The input wire must have been mapped.
136
- assert (wires_mapping.count (this_gate->input_wires [j]) != 0 );
137
- if (wires_mapping[this_gate->input_wires [j]] !=
138
- other_gate->input_wires [j]) {
139
- return false ;
140
- }
141
- } else {
142
- // parameters should not be mapped
143
- if (other_gate->input_wires [j] != this_gate->input_wires [j]) {
144
- return false ;
145
- }
146
- }
147
- }
148
- // Map output wires
149
- for (int j = 0 ; j < (int )this_gate->output_wires .size (); j++) {
150
- assert (wires_mapping.count (this_gate->output_wires [j]) == 0 );
151
- wires_mapping[this_gate->output_wires [j]] =
152
- other_gate->output_wires [j];
153
- wires_to_search.push (this_gate->output_wires [j]);
154
- }
155
110
}
156
111
}
157
112
}
@@ -484,6 +439,16 @@ bool CircuitSeq::remove_gate(CircuitGate *circuit_gate) {
484
439
return true ;
485
440
}
486
441
442
+ bool CircuitSeq::remove_gate_near_end (CircuitGate *circuit_gate) {
443
+ auto gate_pos = std::find_if (
444
+ gates.rbegin (), gates.rend (),
445
+ [&](std::unique_ptr<CircuitGate> &p) { return p.get () == circuit_gate; });
446
+ if (gate_pos == gates.rend ()) {
447
+ return false ;
448
+ }
449
+ return remove_gate ((int )(gates.rend () - gate_pos) - 1 );
450
+ }
451
+
487
452
bool CircuitSeq::remove_first_quantum_gate () {
488
453
for (auto &circuit_gate : gates) {
489
454
if (circuit_gate->gate ->is_quantum_gate ()) {
@@ -1307,6 +1272,35 @@ CircuitSeq::get_permuted_seq(const std::vector<int> &qubit_permutation,
1307
1272
return result;
1308
1273
}
1309
1274
1275
+ std::unique_ptr<CircuitSeq>
1276
+ CircuitSeq::get_suffix_seq (const std::unordered_set<CircuitGate *> &start_gates,
1277
+ Context *ctx) const {
1278
+ // For topological sort
1279
+ std::unordered_map<CircuitGate *, int > gate_remaining_in_degree;
1280
+ for (auto &gate : start_gates) {
1281
+ gate_remaining_in_degree[gate] = 0 ; // ready to include
1282
+ }
1283
+ auto result = std::make_unique<CircuitSeq>(get_num_qubits ());
1284
+ // The result should be a subsequence of this circuit
1285
+ for (auto &gate : gates) {
1286
+ if (gate_remaining_in_degree.count (gate.get ()) > 0 &&
1287
+ gate_remaining_in_degree[gate.get ()] <= 0 ) {
1288
+ result->add_gate (gate.get (), ctx);
1289
+ for (auto &output_wire : gate->output_wires ) {
1290
+ for (auto &output_gate : output_wire->output_gates ) {
1291
+ // For topological sort
1292
+ if (gate_remaining_in_degree.count (output_gate) == 0 ) {
1293
+ gate_remaining_in_degree[output_gate] =
1294
+ output_gate->gate ->get_num_qubits ();
1295
+ }
1296
+ gate_remaining_in_degree[output_gate]--;
1297
+ }
1298
+ }
1299
+ }
1300
+ }
1301
+ return result;
1302
+ }
1303
+
1310
1304
void CircuitSeq::clone_from (const CircuitSeq &other,
1311
1305
const std::vector<int > &qubit_permutation,
1312
1306
const std::vector<int > ¶m_permutation,
@@ -1592,20 +1586,22 @@ std::vector<int> CircuitSeq::first_quantum_gate_positions() const {
1592
1586
return result;
1593
1587
}
1594
1588
1589
+ bool CircuitSeq::is_one_of_last_gates (CircuitGate *circuit_gate) const {
1590
+ for (const auto &output_wire : circuit_gate->output_wires ) {
1591
+ if (outputs[output_wire->index ] != output_wire) {
1592
+ return false ;
1593
+ }
1594
+ }
1595
+ return true ;
1596
+ }
1597
+
1595
1598
std::vector<CircuitGate *> CircuitSeq::last_quantum_gates () const {
1596
1599
std::vector<CircuitGate *> result;
1597
1600
for (const auto &circuit_gate : gates) {
1598
1601
if (circuit_gate->gate ->is_parameter_gate ()) {
1599
1602
continue ;
1600
1603
}
1601
- bool all_output = true ;
1602
- for (const auto &output_wire : circuit_gate->output_wires ) {
1603
- if (outputs[output_wire->index ] != output_wire) {
1604
- all_output = false ;
1605
- break ;
1606
- }
1607
- }
1608
- if (all_output) {
1604
+ if (is_one_of_last_gates (circuit_gate.get ())) {
1609
1605
result.push_back (circuit_gate.get ());
1610
1606
}
1611
1607
}
0 commit comments