Skip to content

Commit ce5f79d

Browse files
authored
[verifier] [bug] Fix a bug when removing common prefix gates and do not generate hashing distribution in test_optimization_steps.h (#208)
1 parent 8276ae5 commit ce5f79d

File tree

5 files changed

+65
-12
lines changed

5 files changed

+65
-12
lines changed

src/benchmark/benchmark_optimization_steps.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ int main() {
4040
auto xfers = GraphXfer::get_all_xfers_from_ecc(
4141
&ctx,
4242
(kQuartzRootPath / "eccset/Nam_6_3_complete_ECC_set.json").string());
43+
int verified_count = 0;
44+
int not_verified_count = 0;
4345
for (const auto &circuit : kCircuitNames) {
4446
freopen(((kQuartzRootPath / "benchmark-logs" / circuit).string() + ".log")
4547
.c_str(),
@@ -57,9 +59,14 @@ int main() {
5759
/*verbose=*/false);
5860
if (verified) {
5961
std::cout << "All transformations are verified." << std::endl;
62+
verified_count++;
6063
} else {
6164
std::cout << "Some transformation is not verified." << std::endl;
65+
not_verified_count++;
66+
std::cerr << circuit << " not verified." << std::endl;
6267
}
6368
}
69+
std::cerr << verified_count << " cases verified, " << not_verified_count
70+
<< " cases not verified." << std::endl;
6471
return 0;
6572
}

src/quartz/dataset/dataset.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ bool Dataset::insert(Context *ctx, std::unique_ptr<CircuitSeq> dag) {
175175
return ret;
176176
}
177177

178+
bool Dataset::insert_with_hash(const CircuitSeqHashType &hash_value,
179+
std::unique_ptr<CircuitSeq> dag) {
180+
bool ret = dataset.count(hash_value) == 0;
181+
dataset[hash_value].push_back(std::move(dag));
182+
return ret;
183+
}
184+
178185
bool Dataset::insert_to_nearby_set_if_exists(Context *ctx,
179186
std::unique_ptr<CircuitSeq> dag) {
180187
const auto hash_value = dag->hash(ctx);

src/quartz/dataset/dataset.h

+12-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,18 @@ class Dataset {
4040
// Returns true iff the hash value is new to the |dataset|.
4141
bool insert(Context *ctx, std::unique_ptr<CircuitSeq> dag);
4242

43-
// Inserts the circuitseq to an existing set if the hash value plus or minus 1
43+
/**
44+
* Insert a CircuitSeq with a pre-defined hash value. This function is used
45+
* when the hash value cannot be computed, and should NOT be used in Quartz's
46+
* generator.
47+
* @param hash_value The hash value to be inserted.
48+
* @param dag The CircuitSeq to be inserted.
49+
* @return True iff the hash value is new to the |dataset|.
50+
*/
51+
bool insert_with_hash(const CircuitSeqHashType &hash_value,
52+
std::unique_ptr<CircuitSeq> dag);
53+
54+
// Inserts the CircuitSeq to an existing set if the hash value plus or minus 1
4455
// is found. Returns true iff there is no such existing set.
4556
bool insert_to_nearby_set_if_exists(Context *ctx,
4657
std::unique_ptr<CircuitSeq> dag);

src/quartz/verifier/verifier.cpp

+35-9
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ bool Verifier::equivalent(Context *ctx, const CircuitSeq *circuit1,
6767
std::unordered_set<CircuitGate *> leftover_gates_start2;
6868
// (Partial) topological sort on circuit1
6969
while (!wires_to_search.empty()) {
70-
auto wire1 = wires_to_search.front();
70+
CircuitWire *wire1 = wires_to_search.front();
7171
assert(wires_mapping.count(wire1) > 0);
7272
auto wire2 = wires_mapping[wire1];
7373
wires_to_search.pop();
@@ -79,19 +79,31 @@ bool Verifier::equivalent(Context *ctx, const CircuitSeq *circuit1,
7979
[&qubit_blocked](CircuitWire *output_wire) {
8080
return qubit_blocked[output_wire->index];
8181
})) {
82-
// Block qubits of potential unmatched gates
83-
for (auto &gate : wire1->output_gates) {
84-
for (auto &output_wire : gate->output_wires) {
85-
qubit_blocked[output_wire->index] = true;
82+
// Block qubits of potential unmatched gates.
83+
for (auto &gate1 : wire1->output_gates) {
84+
// Use a for loop because |wire1->output_gates| can be empty.
85+
for (auto &input_wire : gate1->input_wires) {
86+
qubit_blocked[input_wire->index] = true;
87+
// If |wires_mapping| does not have |input_wire|, this means that
88+
// the qubit is already blocked before, and |leftover_gates_start2|
89+
// already had an earlier gate at this qubit.
90+
if (wires_mapping.count(input_wire) > 0) {
91+
// Note that this input wire might be not in the search queue now.
92+
// We need to manually add the gate in circuit2 to the frontier.
93+
for (auto &gate : wires_mapping[input_wire]->output_gates) {
94+
leftover_gates_start2.insert(gate);
95+
}
96+
}
8697
}
8798
// Use std::unordered_set to deduplicate, similarly hereinafter
88-
leftover_gates_start1.insert(gate);
99+
leftover_gates_start1.insert(gate1);
89100
}
90-
for (auto &gate : wire2->output_gates) {
91-
for (auto &output_wire : gate->output_wires) {
101+
for (auto &gate2 : wire2->output_gates) {
102+
// Use a for loop because |wire2->output_gates| can be empty.
103+
for (auto &output_wire : gate2->output_wires) {
92104
qubit_blocked[output_wire->index] = true;
93105
}
94-
leftover_gates_start2.insert(gate);
106+
leftover_gates_start2.insert(gate2);
95107
}
96108
continue;
97109
}
@@ -141,6 +153,20 @@ bool Verifier::equivalent(Context *ctx, const CircuitSeq *circuit1,
141153
// We should have removed the same number of gates
142154
assert(circuit1->get_num_gates() - c1->get_num_gates() ==
143155
circuit2->get_num_gates() - c2->get_num_gates());
156+
if (verbose) {
157+
std::cout << "Removed " << circuit1->get_num_gates() - c1->get_num_gates()
158+
<< " prefix gates from circuit1 and "
159+
<< circuit2->get_num_gates() - c2->get_num_gates()
160+
<< " prefix gates from circuit2." << std::endl;
161+
std::cout << "Leftover gates from circuit1:" << std::endl;
162+
for (auto &gate : leftover_gates_start1) {
163+
std::cout << gate->to_string() << std::endl;
164+
}
165+
std::cout << "Leftover gates from circuit2:" << std::endl;
166+
for (auto &gate : leftover_gates_start2) {
167+
std::cout << gate->to_string() << std::endl;
168+
}
169+
}
144170

145171
// Remove common last gates
146172
while (true) {

src/test/test_optimization_steps.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ void test_optimization(
2121
std::cerr << "Parser failed" << std::endl;
2222
return;
2323
}
24-
ctx->gen_input_and_hashing_dis(dag->get_num_qubits());
24+
// Do not generate (this is only for CircuitSeq::hash())
25+
// because the number of qubits can be large.
26+
// ctx->gen_input_and_hashing_dis(dag->get_num_qubits());
2527

26-
quartz::Graph graph(ctx, dag);
28+
Graph graph(ctx, dag);
2729
std::cout << graph.total_cost() << " gates in circuit before optimizing."
2830
<< std::endl;
2931
auto start = std::chrono::steady_clock::now();

0 commit comments

Comments
 (0)