Skip to content

Commit 1bc5f2f

Browse files
authored
[optimizer] Add a benchmark for optimization steps (#205)
1 parent 67c7f9d commit 1bc5f2f

7 files changed

+121
-43
lines changed

src/benchmark/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ file(GLOB_RECURSE NAM_SMALL_CIRCUITS "nam_small_circuits.cpp")
77
add_executable(benchmark_nam_small_circuits ${NAM_SMALL_CIRCUITS})
88
file(GLOB_RECURSE NAM_MIDDLE_CIRCUITS "nam_middle_circuits.cpp")
99
add_executable(benchmark_nam_middle_circuits ${NAM_MIDDLE_CIRCUITS})
10+
file(GLOB_RECURSE OPTIMIZATION_STEPS "benchmark_optimization_steps.cpp")
11+
add_executable(benchmark_optimization_steps ${OPTIMIZATION_STEPS})
1012

1113
# TODO: Rename them
1214
file(GLOB_RECURSE ILP_NUM_STAGES "ilp_num_stages.cpp")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include "quartz/gate/gate_utils.h"
2+
#include "quartz/verifier/verifier.h"
3+
#include "test/test_optimization_steps.h"
4+
5+
#include <filesystem>
6+
#include <iostream>
7+
8+
using namespace quartz;
9+
10+
const std::vector<std::string> kCircuitNames = {
11+
"tof_3", "barenco_tof_3", "mod5_4", "tof_4",
12+
"tof_5", "barenco_tof_4", "mod_mult_55", "vbe_adder_3",
13+
"barenco_tof_5", "csla_mux_3", "rc_adder_6", "gf2^4_mult",
14+
"tof_10", "mod_red_21", "gf2^5_mult", "csum_mux_9",
15+
"qcla_com_7", "barenco_tof_10", "gf2^6_mult", "qcla_adder_10",
16+
"gf2^7_mult", "gf2^8_mult", "qcla_mod_7", "adder_8",
17+
"gf2^9_mult", "gf2^10_mult"};
18+
int main() {
19+
ParamInfo param_info;
20+
Context ctx({GateType::input_qubit, GateType::input_param, GateType::cx,
21+
GateType::h, GateType::rz, GateType::x, GateType::pi,
22+
GateType::mult, GateType::add},
23+
&param_info);
24+
EquivalenceSet eqs;
25+
// Load equivalent dags from file
26+
if (!eqs.load_json(
27+
&ctx,
28+
(kQuartzRootPath / "eccset/Nam_6_3_complete_ECC_set.json").string(),
29+
/*from_verifier=*/false)) {
30+
std::cout
31+
<< "Failed to load equivalence file \""
32+
<< (kQuartzRootPath / "eccset/Nam_6_3_complete_ECC_set.json").string()
33+
<< "\"." << std::endl;
34+
assert(false);
35+
}
36+
if (!std::filesystem::exists(kQuartzRootPath / "benchmark-logs")) {
37+
std::filesystem::create_directory(kQuartzRootPath / "benchmark-logs");
38+
}
39+
Verifier verifier;
40+
auto xfers = GraphXfer::get_all_xfers_from_ecc(
41+
&ctx,
42+
(kQuartzRootPath / "eccset/Nam_6_3_complete_ECC_set.json").string());
43+
for (const auto &circuit : kCircuitNames) {
44+
freopen(((kQuartzRootPath / "benchmark-logs" / circuit).string() + ".log")
45+
.c_str(),
46+
"w", stdout);
47+
test_optimization(&ctx,
48+
(kQuartzRootPath / "circuit/nam-benchmarks" /
49+
(circuit + ".qasm.toffoli_flip"))
50+
.string(),
51+
xfers,
52+
/*timeout=*/1,
53+
(kQuartzRootPath / "benchmark-logs" / circuit).string() +
54+
"_");
55+
bool verified = verifier.verify_transformation_steps(
56+
&ctx, (kQuartzRootPath / "benchmark-logs" / circuit).string() + "_",
57+
/*verbose=*/false);
58+
if (verified) {
59+
std::cout << "All transformations are verified." << std::endl;
60+
} else {
61+
std::cout << "Some transformation is not verified." << std::endl;
62+
}
63+
}
64+
return 0;
65+
}

src/quartz/tasograph/substitution.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,46 @@ GraphXfer::ccz_cx_t_xfer(Context *src_ctx, Context *dst_ctx,
549549
return std::make_pair(xfer_0, xfer_1);
550550
}
551551

552+
std::vector<GraphXfer *>
553+
GraphXfer::get_all_xfers_from_ecc(Context *ctx,
554+
const std::string &equiv_file_name) {
555+
EquivalenceSet eqs;
556+
// Load equivalent dags from file
557+
if (!eqs.load_json(ctx, equiv_file_name, /*from_verifier=*/false)) {
558+
std::cout << "Failed to load equivalence file \"" << equiv_file_name
559+
<< "\"." << std::endl;
560+
assert(false);
561+
}
562+
563+
auto eccs = eqs.get_all_equivalence_sets();
564+
std::vector<GraphXfer *> xfers;
565+
for (const auto &ecc : eccs) {
566+
CircuitSeq *representative = ecc.front();
567+
/*int representative_depth = representative->get_circuit_depth();
568+
for (auto &circuit : ecc) {
569+
int circuit_depth = circuit->get_circuit_depth();
570+
if (circuit_depth < representative_depth) {
571+
representative = circuit;
572+
representative_depth = circuit_depth;
573+
}
574+
}*/
575+
for (auto &circuit : ecc) {
576+
if (circuit != representative) {
577+
auto xfer =
578+
GraphXfer::create_GraphXfer(ctx, circuit, representative, true);
579+
if (xfer != nullptr) {
580+
xfers.push_back(xfer);
581+
}
582+
xfer = GraphXfer::create_GraphXfer(ctx, representative, circuit, true);
583+
if (xfer != nullptr) {
584+
xfers.push_back(xfer);
585+
}
586+
}
587+
}
588+
}
589+
return xfers;
590+
}
591+
552592
GraphXfer::GraphXfer(Context *src_ctx, Context *dst_ctx, Context *union_ctx,
553593
const CircuitSeq *src_graph, const CircuitSeq *dst_graph)
554594
: src_ctx_(src_ctx), dst_ctx_(dst_ctx), union_ctx_(union_ctx), tensorId(0) {

src/quartz/tasograph/substitution.h

+2
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ class GraphXfer {
130130
ccz_cx_u1_xfer(Context *src_ctx, Context *dst_ctx, Context *union_ctx);
131131
static std::pair<GraphXfer *, GraphXfer *>
132132
ccz_cx_t_xfer(Context *src_ctx, Context *dst_ctx, Context *union_ctx);
133+
static std::vector<GraphXfer *>
134+
get_all_xfers_from_ecc(Context *ctx, const std::string &equiv_file_name);
133135

134136
public:
135137
Context *src_ctx_;

src/quartz/tasograph/tasograph.cpp

+2-35
Original file line numberDiff line numberDiff line change
@@ -1921,42 +1921,9 @@ Graph::optimize(Context *ctx, const std::string &equiv_file_name,
19211921
if (cost_function == nullptr) {
19221922
cost_function = [](Graph *graph) { return graph->total_cost(); };
19231923
}
1924-
1925-
EquivalenceSet eqs;
1926-
// Load equivalent dags from file
1927-
if (!eqs.load_json(ctx, equiv_file_name, /*from_verifier=*/false)) {
1928-
std::cout << "Failed to load equivalence file \"" << equiv_file_name
1929-
<< "\"." << std::endl;
1930-
assert(false);
1931-
}
1932-
19331924
// Get xfer from the equivalent set
1934-
auto eccs = eqs.get_all_equivalence_sets();
1935-
std::vector<GraphXfer *> xfers;
1936-
for (const auto &ecc : eccs) {
1937-
CircuitSeq *representative = ecc.front();
1938-
/*int representative_depth = representative->get_circuit_depth();
1939-
for (auto &circuit : ecc) {
1940-
int circuit_depth = circuit->get_circuit_depth();
1941-
if (circuit_depth < representative_depth) {
1942-
representative = circuit;
1943-
representative_depth = circuit_depth;
1944-
}
1945-
}*/
1946-
for (auto &circuit : ecc) {
1947-
if (circuit != representative) {
1948-
auto xfer =
1949-
GraphXfer::create_GraphXfer(ctx, circuit, representative, true);
1950-
if (xfer != nullptr) {
1951-
xfers.push_back(xfer);
1952-
}
1953-
xfer = GraphXfer::create_GraphXfer(ctx, representative, circuit, true);
1954-
if (xfer != nullptr) {
1955-
xfers.push_back(xfer);
1956-
}
1957-
}
1958-
}
1959-
}
1925+
std::vector<GraphXfer *> xfers =
1926+
GraphXfer::get_all_xfers_from_ecc(ctx, equiv_file_name);
19601927
if (print_message) {
19611928
std::cout << "Number of xfers: " << xfers.size() << std::endl;
19621929
}

src/test/test_optimization_steps.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,19 @@ int main() {
1717
if (!std::filesystem::exists(kQuartzRootPath / "logs")) {
1818
std::filesystem::create_directory(kQuartzRootPath / "logs");
1919
}
20+
auto xfers = GraphXfer::get_all_xfers_from_ecc(
21+
&ctx, (kQuartzRootPath / "eccset/Clifford_T_5_3_complete_ECC_set.json")
22+
.string());
2023
test_optimization(
2124
&ctx,
2225
(kQuartzRootPath / "circuit/example-circuits/barenco_tof_3.qasm")
2326
.string(),
24-
(kQuartzRootPath / "eccset/Clifford_T_5_3_complete_ECC_set.json")
25-
.string(),
27+
xfers,
2628
/*timeout=*/12, (kQuartzRootPath / "logs/barenco_tof_3_").string());
2729
Verifier verifier;
2830
bool verified = verifier.verify_transformation_steps(
2931
&ctx, (kQuartzRootPath / "logs/barenco_tof_3_").string(),
30-
/*verbose=*/true);
32+
/*verbose=*/false);
3133
if (verified) {
3234
std::cout << "All transformations are verified." << std::endl;
3335
} else {

src/test/test_optimization_steps.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ using namespace quartz;
1313

1414
void test_optimization(
1515
Context *ctx, const std::string &file_name,
16-
const std::string &equivalent_file_name, double timeout,
16+
const std::vector<GraphXfer *> &xfers, double timeout,
1717
const std::string &store_all_steps_file_prefix = std::string()) {
1818
QASMParser qasm_parser(ctx);
1919
CircuitSeq *dag = nullptr;
@@ -27,10 +27,10 @@ void test_optimization(
2727
std::cout << graph.total_cost() << " gates in circuit before optimizing."
2828
<< std::endl;
2929
auto start = std::chrono::steady_clock::now();
30-
auto new_graph =
31-
graph.optimize(ctx, equivalent_file_name, file_name, /*print_message=*/
32-
true, /*cost_function=*/nullptr, /*cost_upper_bound=*/-1,
33-
timeout, store_all_steps_file_prefix);
30+
auto new_graph = graph.optimize(xfers, graph.total_cost() * 1.05, file_name,
31+
/*log_file_name=*/"", /*print_message=*/
32+
true, /*cost_function=*/nullptr, timeout,
33+
store_all_steps_file_prefix);
3434
auto end = std::chrono::steady_clock::now();
3535
std::cout << "After optimizing graph in "
3636
<< (double)std::chrono::duration_cast<std::chrono::milliseconds>(

0 commit comments

Comments
 (0)