From f0aa086d84668a718c96dc73fdb1156496b3875a Mon Sep 17 00:00:00 2001 From: Kevin Guo Date: Tue, 26 Sep 2023 12:02:51 -0400 Subject: [PATCH] refactor; create GridSynthesizer --- include/grid_synth/exact_synthesis.hpp | 16 +- include/grid_synth/grid_synth.hpp | 254 +++++++++++++++++++++++++ include/grid_synth/s3_table.hpp | 6 + include/transformations/qasm_synth.hpp | 190 +----------------- tools/grid_synth.cpp | 159 +--------------- tools/qasm_synth.cpp | 9 +- 6 files changed, 291 insertions(+), 343 deletions(-) create mode 100644 include/grid_synth/grid_synth.hpp create mode 100644 include/grid_synth/s3_table.hpp diff --git a/include/grid_synth/exact_synthesis.hpp b/include/grid_synth/exact_synthesis.hpp index db66e0de..68c0362f 100644 --- a/include/grid_synth/exact_synthesis.hpp +++ b/include/grid_synth/exact_synthesis.hpp @@ -45,21 +45,21 @@ inline str_t check_common_cases(real_t theta, const real_t& eps) { theta = theta + real_t("2"); if (abs(theta - real_t("0.25")) < eps) { - return "T w"; + return "Tw"; } else if (abs(theta - real_t("0.5")) < eps) { - return "S W W W W W W W"; + return "SWWWWWWW"; } else if (abs(theta - real_t("0.75")) < eps) { - return "S T W W W W W W W w"; + return "STWWWWWWWw"; } else if (abs(theta - real_t("1")) < eps) { - return "S S W W W W W W"; + return "SSWWWWWW"; } else if (abs(theta - real_t("1.25")) < eps) { - return "S S T W W W W W W w"; + return "SSTWWWWWWw"; } else if (abs(theta - real_t("1.5")) < eps) { - return "S S S W W W W W"; + return "SSSWWWWW"; } else if (abs(theta - real_t("1.75")) < eps) { - return "S S S T W W W W W w"; + return "SSSTWWWWWw"; } else if (abs(theta - real_t("2")) < eps) { - return "W W W W"; + return "WWWW"; } else { return ""; } diff --git a/include/grid_synth/grid_synth.hpp b/include/grid_synth/grid_synth.hpp new file mode 100644 index 00000000..9c4fdb91 --- /dev/null +++ b/include/grid_synth/grid_synth.hpp @@ -0,0 +1,254 @@ +/* + * This file is part of staq. + * + * Copyright (c) 2019 - 2023 softwareQ Inc. All rights reserved. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef GRID_SYNTH_GRID_SYNTH_HPP_ +#define GRID_SYNTH_GRID_SYNTH_HPP_ + +#include "grid_synth/exact_synthesis.hpp" +#include "grid_synth/matrix.hpp" +#include "grid_synth/rz_approximation.hpp" +#include "grid_synth/types.hpp" + +namespace staq { +namespace grid_synth { + +/*! \brief Converts a GMP float to a string suitable for hashing. */ +static str_t to_string(const mpf_class& x) { + mp_exp_t exp; + // Use base 32 to get a shorter string. + // Truncate to keep only the significant figures. + str_t s = x.get_str(exp, 32).substr(0, mpf_get_default_prec() / 5); + return s + str_t(" ") + std::to_string(exp); +} + +struct GridSynthOptions { + long int prec; + int factor_effort = MAX_ATTEMPTS_POLLARD_RHO; + str_t tablefile = ""; + bool read = false; + bool write = false; + bool check = false; + bool details = false; + bool verbose = false; + bool timer = false; +}; + +class GridSynthesizer { + private: + std::unordered_map rz_approx_cache_; + domega_matrix_table_t s3_table_; + real_t eps_; + bool check_; + bool details_; + bool verbose_; + bool timer_; + long long duration_; + + GridSynthesizer(domega_matrix_table_t s3_table, real_t eps, bool check, + bool details, bool verbose, bool timer) + : rz_approx_cache_(), s3_table_(s3_table), eps_(eps), check_(check), + details_(details), verbose_(verbose), timer_(timer), duration_(0) {} + + public: + ~GridSynthesizer() { + if (timer_) { + std::cerr << std::fixed + << "Duration = " << (static_cast(duration_) / 1e6) + << " seconds" << '\n'; + } + } + + /*! \brief Find RZ-approximation for an angle. */ + str_t get_rz_approx(const real_t& angle) { + if (verbose_) + std::cerr << "Checking common cases..." + << "\n"; + str_t common_case = check_common_cases(angle / gmpf::gmp_pi(), eps_); + if (common_case != "") { + if (details_) + std::cerr + << "Angle is multiple of pi/4, answer is known exactly" + << '\n'; + if (check_) + std::cerr << "Check flag = " << 1 << '\n'; + return common_case; + } + if (verbose_) + std::cerr << "No common cases found" << '\n'; + + RzApproximation rz_approx; + str_t op_str; + if (timer_) { + // If timer is enabled, don't check cache or produce debug + // output. Just synthesize the angle. + auto start = std::chrono::steady_clock::now(); + rz_approx = find_fast_rz_approximation( + real_t(angle) * PI / real_t("-2"), eps_); + op_str = synthesize(rz_approx.matrix(), s3_table_); + auto end = std::chrono::steady_clock::now(); + duration_ += std::chrono::duration_cast( + end - start) + .count(); + } else { + str_t angle_str = to_string(angle); + if (verbose_) + std::cerr << "Checking local cache..." << '\n'; + if (details_) + std::cerr << "Angle has string representation " << angle_str + << '\n'; + if (rz_approx_cache_.count(angle_str)) { + if (verbose_ || details_) + std::cerr << "Angle is found in local cache" << '\n'; + return rz_approx_cache_[angle_str]; + } + + if (verbose_) + std::cerr + << "Running grid_synth to find new rz approximation..." + << '\n'; + RzApproximation rz_approx = + find_fast_rz_approximation(angle / real_t("-2.0"), eps_); + if (!rz_approx.solution_found()) { + std::cerr << "No approximation found for RzApproximation. " + "Try changing factorization effort." + << '\n'; + exit(EXIT_FAILURE); + } + if (verbose_) + std::cerr << "Approximation found. Synthesizing..." << '\n'; + op_str = synthesize(rz_approx.matrix(), s3_table_); + + if (verbose_) + std::cerr << "Synthesis complete." << '\n'; + if (check_) { + std::cerr << "Check flag = " + << (rz_approx.matrix() == + domega_matrix_from_str(full_simplify_str(op_str))) + << '\n'; + } + if (details_) { + real_t scale = gmpf::pow(SQRT2, rz_approx.matrix().k()); + std::cerr << "angle = " << std::scientific << angle << '\n'; + std::cerr << rz_approx.matrix(); + std::cerr << "u decimal value = " + << "(" + << rz_approx.matrix().u().decimal().real() / scale + << "," + << rz_approx.matrix().u().decimal().imag() / scale + << ")" << '\n'; + std::cerr << "t decimal value = " + << "(" + << rz_approx.matrix().t().decimal().real() / scale + << "," + << rz_approx.matrix().t().decimal().imag() / scale + << ")" << '\n'; + std::cerr << "error = " << rz_approx.error() << '\n'; + str_t simplified = full_simplify_str(op_str); + std::string::difference_type n = + count(simplified.begin(), simplified.end(), 'T'); + std::cerr << "T count = " << n << '\n'; + std::cerr << "----" << '\n' << std::fixed; + } + rz_approx_cache_[angle_str] = op_str; + } + return op_str; + } + + friend GridSynthesizer make_synthesizer(const GridSynthOptions& opt); +}; + +/*! \brief Initializes a GridSynthesizer object. */ +GridSynthesizer make_synthesizer(const GridSynthOptions& opt) { + domega_matrix_table_t s3_table; + real_t eps; + + if (opt.read) { + if (opt.verbose) { + std::cerr << "Reading s3_table from " << opt.tablefile << '\n'; + } + s3_table = read_s3_table(opt.tablefile); + } else if (opt.write) { + if (opt.verbose) { + std::cerr << "Generating new table file and writing to " + << opt.tablefile << '\n'; + } + s3_table = generate_s3_table(); + write_s3_table(opt.tablefile, s3_table); + } else if (std::ifstream(DEFAULT_TABLE_FILE)) { + if (opt.verbose) { + std::cerr << "Table file found at default location " + << DEFAULT_TABLE_FILE << '\n'; + } + s3_table = read_s3_table(DEFAULT_TABLE_FILE); + } else { + if (opt.verbose) { + std::cerr << "Failed to find " << DEFAULT_TABLE_FILE + << ". Generating new table file and writing to " + << DEFAULT_TABLE_FILE << '\n'; + } + s3_table = generate_s3_table(); + write_s3_table(DEFAULT_TABLE_FILE, s3_table); + } + + MP_CONSTS = initialize_constants(opt.prec); + eps = gmpf::pow(real_t(10), -opt.prec); + MAX_ATTEMPTS_POLLARD_RHO = opt.factor_effort; + + if (opt.verbose) { + std::cerr << "Runtime Parameters" << '\n'; + std::cerr << "------------------" << '\n'; + std::cerr << std::setw(3 * COLW) << std::left + << "TOL (Tolerance for float equality) " << std::setw(1) + << ": " << std::setw(3 * COLW) << std::left << std::scientific + << TOL << '\n'; + std::cerr << std::setw(3 * COLW) << std::left + << "KMIN (Minimum scaling exponent) " << std::setw(1) << ": " + << std::setw(3 * COLW) << std::left << std::fixed << KMIN + << '\n'; + std::cerr << std::setw(2 * COLW) << std::left + << "KMAX (Maximum scaling exponent) " << std::setw(1) << ": " + << std::setw(3 * COLW) << std::left << std::fixed << KMAX + << '\n'; + std::cerr << std::setw(3 * COLW) << std::left + << "MAX_ATTEMPTS_POLLARD_RHO (How hard we try to factor) " + << std::setw(1) << ": " << std::setw(3 * COLW) << std::left + << MAX_ATTEMPTS_POLLARD_RHO << '\n'; + std::cerr << std::setw(3 * COLW) << std::left + << "MAX_ITERATIONS_FERMAT_TEST (How hard we try to check " + "primality) " + << std::setw(1) << ": " << std::setw(3 * COLW) << std::left + << MAX_ITERATIONS_FERMAT_TEST << '\n'; + } + std::cerr << std::scientific; + + return GridSynthesizer(std::move(s3_table), std::move(eps), opt.check, + opt.details, opt.verbose, opt.timer); +} + +} // namespace grid_synth +} // namespace staq + +#endif // GRID_SYNTH_GRID_SYNTH_HPP_ diff --git a/include/grid_synth/s3_table.hpp b/include/grid_synth/s3_table.hpp new file mode 100644 index 00000000..16ce52a7 --- /dev/null +++ b/include/grid_synth/s3_table.hpp @@ -0,0 +1,6 @@ + + +//include guard + + +std::unordered_map s3_table_{k1:v1, k2:v2}... \ No newline at end of file diff --git a/include/transformations/qasm_synth.hpp b/include/transformations/qasm_synth.hpp index c44ec130..f742f6cd 100644 --- a/include/transformations/qasm_synth.hpp +++ b/include/transformations/qasm_synth.hpp @@ -36,6 +36,7 @@ #include #include "grid_synth/exact_synthesis.hpp" +#include "grid_synth/grid_synth.hpp" #include "grid_synth/rz_approximation.hpp" #include "grid_synth/types.hpp" #include "qasmtools/ast/replacer.hpp" @@ -45,27 +46,14 @@ namespace staq { namespace transformations { namespace ast = qasmtools::ast; -using real_t = staq::grid_synth::real_t; -using str_t = staq::grid_synth::str_t; - -struct QASMSynthOptions { - long int prec; - int factor_effort; - str_t tablefile; - bool read; - bool write; - bool check; - bool details; - bool verbose; -}; +using namespace grid_synth; /* Implementation */ class QASMSynthImpl final : public ast::Replacer { public: - QASMSynthImpl(grid_synth::domega_matrix_table_t& s3_table, real_t& eps, - const QASMSynthOptions& opt) - : s3_table_(s3_table), eps_(eps), check_(opt.check), - details_(opt.details), verbose_(opt.verbose), w_count_(0){}; + QASMSynthImpl(const GridSynthOptions& opt) + : synthesizer_(make_synthesizer(opt)), w_count_(0), check_(opt.check), + details_(opt.details), verbose_(opt.verbose){}; ~QASMSynthImpl() = default; void run(ast::ASTNode& node) { node.accept(*this); } @@ -105,7 +93,7 @@ class QASMSynthImpl final : public ast::Replacer { << ": finding approximation for angle = " << (angle) << '\n'; } - std::string rz_approx = get_rz_approx(angle); + std::string rz_approx = synthesizer_.get_rz_approx(angle); if (details_) { std::cerr << gate.pos() << ": found approximation " << rz_approx << '\n'; @@ -177,24 +165,11 @@ class QASMSynthImpl final : public ast::Replacer { } private: - grid_synth::domega_matrix_table_t& s3_table_; - real_t& eps_; + GridSynthesizer synthesizer_; + int w_count_; bool check_; bool details_; bool verbose_; - std::unordered_map rz_approx_cache_; - int w_count_; - - /** - * Converts a GMP float to a string representation suitable for hashing. - */ - std::string to_string(const mpf_class& x) const { - mp_exp_t exp; - // Use base 32 to get a shorter string. - std::string s = - x.get_str(exp, 32).substr(0, mpf_get_default_prec() / 5); - return s + std::string(" ") + std::to_string(exp); - } /*! * \brief Makes a new gate with no cargs. @@ -209,158 +184,13 @@ class QASMSynthImpl final : public ast::Replacer { return std::make_unique(ast::DeclaredGate( gate.pos(), name, std::move(c_args), std::move(q_args))); } - - /*! \brief Find RZ-approximation for an angle using grid_synth. */ - std::string get_rz_approx(const real_t& angle) { - using namespace grid_synth; - - if (verbose_) - std::cerr << "Checking common cases..." - << "\n"; - std::string ret = check_common_cases(angle / gmpf::gmp_pi(), eps_); - if (ret != "") { - if (details_) - std::cerr - << "Angle is multiple of pi/4, answer is known exactly" - << '\n'; - if (check_) - std::cerr << "Check flag = " << 1 << '\n'; - std::string ret_no_spaces; - for (char c : ret) { - if (c != ' ') - ret_no_spaces.push_back(c); - } - return ret_no_spaces; - } - - std::string angle_str = to_string(angle); - if (verbose_) { - std::cerr << "Checking local cache..." << '\n'; - std::cerr << "Angle has string representation " << angle_str - << '\n'; - } - if (rz_approx_cache_.count(angle_str)) { - if (verbose_ || details_) - std::cerr << "Angle is found in local cache" << '\n'; - return rz_approx_cache_[angle_str]; - } - - if (verbose_) - std::cerr << "Running grid_synth to find new rz approximation..." - << '\n'; - RzApproximation rz_approx = - find_fast_rz_approximation(angle / real_t("-2.0"), eps_); - if (!rz_approx.solution_found()) { - std::cerr << "No approximation found for RzApproximation. " - "Try changing factorization effort." - << '\n'; - exit(EXIT_FAILURE); // TODO: change this to fail more gracefully? - } - if (verbose_) - std::cerr << "Approximation found. Synthesizing..." << '\n'; - ret = synthesize(rz_approx.matrix(), s3_table_); - - if (verbose_) - std::cerr << "Synthesis complete." << '\n'; - if (check_) { - std::cerr << "Check flag = " - << (rz_approx.matrix() == - domega_matrix_from_str(full_simplify_str(ret))) - << '\n'; - } - if (details_) { - real_t scale = gmpf::pow(SQRT2, rz_approx.matrix().k()); - std::cerr << "angle = " << std::scientific << angle << '\n'; - std::cerr << rz_approx.matrix(); - std::cerr << "u decimal value = " - << "(" << rz_approx.matrix().u().decimal().real() / scale - << "," << rz_approx.matrix().u().decimal().imag() / scale - << ")" << '\n'; - std::cerr << "t decimal value = " - << "(" << rz_approx.matrix().t().decimal().real() / scale - << "," << rz_approx.matrix().t().decimal().imag() / scale - << ")" << '\n'; - std::cerr << "error = " << rz_approx.error() << '\n'; - str_t simplified = full_simplify_str(ret); - std::string::difference_type n = - count(simplified.begin(), simplified.end(), 'T'); - std::cerr << "T count = " << n << '\n'; - std::cerr << "----" << '\n' << std::fixed; - } - - rz_approx_cache_[angle_str] = ret; - return ret; - } }; /** * Replaces all rx/ry/rz gates in a program with grid_synth approximations. */ -void qasm_synth(ast::ASTNode& node, const QASMSynthOptions& opt) { - using namespace grid_synth; - domega_matrix_table_t s3_table; - real_t eps; - - if (opt.read) { - if (opt.verbose) { - std::cerr << "Reading s3_table from " << opt.tablefile << '\n'; - } - s3_table = read_s3_table(opt.tablefile); - } else if (opt.write) { - if (opt.verbose) { - std::cerr << "Generating new table file and writing to " - << opt.tablefile << '\n'; - } - s3_table = generate_s3_table(); - write_s3_table(opt.tablefile, s3_table); - } else if (std::ifstream(DEFAULT_TABLE_FILE)) { - if (opt.verbose) { - std::cerr << "Table file found at default location " - << DEFAULT_TABLE_FILE << '\n'; - } - s3_table = read_s3_table(DEFAULT_TABLE_FILE); - } else { - if (opt.verbose) { - std::cerr << "Failed to find " << DEFAULT_TABLE_FILE - << ". Generating new table file and writing to " - << DEFAULT_TABLE_FILE << '\n'; - } - s3_table = generate_s3_table(); - write_s3_table(DEFAULT_TABLE_FILE, s3_table); - } - - MP_CONSTS = initialize_constants(opt.prec); - eps = gmpf::pow(real_t(10), -opt.prec); - MAX_ATTEMPTS_POLLARD_RHO = opt.factor_effort; - - if (opt.verbose) { - std::cerr << "Runtime Parameters" << '\n'; - std::cerr << "------------------" << '\n'; - std::cerr << std::setw(3 * COLW) << std::left - << "TOL (Tolerance for float equality) " << std::setw(1) - << ": " << std::setw(3 * COLW) << std::left << std::scientific - << TOL << '\n'; - std::cerr << std::setw(3 * COLW) << std::left - << "KMIN (Minimum scaling exponent) " << std::setw(1) << ": " - << std::setw(3 * COLW) << std::left << std::fixed << KMIN - << '\n'; - std::cerr << std::setw(2 * COLW) << std::left - << "KMAX (Maximum scaling exponent) " << std::setw(1) << ": " - << std::setw(3 * COLW) << std::left << std::fixed << KMAX - << '\n'; - std::cerr << std::setw(3 * COLW) << std::left - << "MAX_ATTEMPTS_POLLARD_RHO (How hard we try to factor) " - << std::setw(1) << ": " << std::setw(3 * COLW) << std::left - << MAX_ATTEMPTS_POLLARD_RHO << '\n'; - std::cerr << std::setw(3 * COLW) << std::left - << "MAX_ITERATIONS_FERMAT_TEST (How hard we try to check " - "primality) " - << std::setw(1) << ": " << std::setw(3 * COLW) << std::left - << MAX_ITERATIONS_FERMAT_TEST << '\n'; - } - std::cerr << std::scientific; - - QASMSynthImpl alg(s3_table, eps, opt); +void qasm_synth(ast::ASTNode& node, const GridSynthOptions& opt) { + QASMSynthImpl alg(opt); alg.run(node); alg.print_global_phase(); } diff --git a/tools/grid_synth.cpp b/tools/grid_synth.cpp index 0e4b2618..f15559bd 100644 --- a/tools/grid_synth.cpp +++ b/tools/grid_synth.cpp @@ -31,6 +31,7 @@ #include #include "grid_synth/exact_synthesis.hpp" +#include "grid_synth/grid_synth.hpp" #include "grid_synth/regions.hpp" #include "grid_synth/rz_approximation.hpp" #include "grid_synth/types.hpp" @@ -90,163 +91,21 @@ int main(int argc, char** argv) { std::cerr << thetas.size() << " angles read." << '\n'; } - if (*read) { - if (verbose) { - std::cerr << "Reading s3_table from " << tablefile << '\n'; - } - s3_table = read_s3_table(tablefile); - } else if (*write) { - if (verbose) { - std::cerr << "Generating new table file and writing to " - << tablefile << '\n'; - } - s3_table = generate_s3_table(); - write_s3_table(tablefile, s3_table); - } else if (std::ifstream(DEFAULT_TABLE_FILE)) { - if (verbose) { - std::cerr << "Table file found at default location " - << DEFAULT_TABLE_FILE << '\n'; - } - s3_table = read_s3_table(DEFAULT_TABLE_FILE); - } else { - if (verbose) { - std::cerr << "Failed to find " << DEFAULT_TABLE_FILE - << ". Generating new table file and writing to " - << DEFAULT_TABLE_FILE << '\n'; - } - s3_table = generate_s3_table(); - write_s3_table(DEFAULT_TABLE_FILE, s3_table); - } - - MP_CONSTS = initialize_constants(prec); - eps = gmpf::pow(real_t(10), -prec); - MAX_ATTEMPTS_POLLARD_RHO = factor_effort; - - if (verbose) { - std::cerr << "Runtime Parameters" << '\n'; - std::cerr << "------------------" << '\n'; - std::cerr << std::setw(3 * COLW) << std::left - << "TOL (Tolerance for float equality) " << std::setw(1) - << ": " << std::setw(3 * COLW) << std::left << std::scientific - << TOL << '\n'; - std::cerr << std::setw(3 * COLW) << std::left - << "KMIN (Minimum scaling exponent) " << std::setw(1) << ": " - << std::setw(3 * COLW) << std::left << std::fixed << KMIN - << '\n'; - std::cerr << std::setw(2 * COLW) << std::left - << "KMAX (Maximum scaling exponent) " << std::setw(1) << ": " - << std::setw(3 * COLW) << std::left << std::fixed << KMAX - << '\n'; - std::cerr << std::setw(3 * COLW) << std::left - << "MAX_ATTEMPTS_POLLARD_RHO (How hard we try to factor) " - << std::setw(1) << ": " << std::setw(3 * COLW) << std::left - << MAX_ATTEMPTS_POLLARD_RHO << '\n'; - std::cerr << std::setw(3 * COLW) << std::left - << "MAX_ITERATIONS_FERMAT_TEST (How hard we try to check " - "primality) " - << std::setw(1) << ": " << std::setw(3 * COLW) << std::left - << MAX_ITERATIONS_FERMAT_TEST << '\n'; - } - std::cerr << std::scientific; + GridSynthOptions opt{prec, factor_effort, std::move(tablefile), + (bool)*read, (bool)*write, check, + details, verbose, timer}; + GridSynthesizer synthesizer = make_synthesizer(opt); - long long duration = 0; if (*prec_opt && *thetas_op) { std::random_device rd; random_numbers.seed(rd()); for (const auto& angle : thetas) { - str_t common_case = check_common_cases(real_t(angle), eps); - if (verbose) - std::cerr << "Checking common cases..." << '\n'; - if (common_case != "") { - if (details) - std::cerr - << "Angle is multiple of pi/4, answer is known exactly" - << '\n'; - if (check) { - std::cerr << "Check flag = " << 1 << '\n'; - } - std::cout << common_case << '\n'; - return 0; - } - if (verbose) - std::cerr << "No common cases found" << '\n'; - - RzApproximation rz_approx; - if (timer) { - auto start = std::chrono::steady_clock::now(); - rz_approx = find_fast_rz_approximation( - real_t(angle) * PI / real_t("-2"), eps); - str_t op_str = synthesize(rz_approx.matrix(), s3_table); - auto end = std::chrono::steady_clock::now(); - duration += - std::chrono::duration_cast(end - - start) - .count(); - } else { - if (verbose) { - std::cerr << "----\n"; - std::cerr << "Finding approximation for angle = " << (angle) - << "..." << '\n'; - } - rz_approx = find_fast_rz_approximation( - real_t(angle) * PI / real_t("-2"), eps); - if (!rz_approx.solution_found()) { - std::cerr << "No approximation found for RzApproximation. " - "Try changing factorization effort." - << '\n'; - return EXIT_FAILURE; - } - if (verbose) { - std::cerr << "Approximation found. Synthesizing..." << '\n'; - } - str_t op_str = synthesize(rz_approx.matrix(), s3_table); - if (verbose) { - std::cerr << "Synthesis complete." << '\n'; - } - - if (check) { - std::cerr - << "Check flag = " - << (rz_approx.matrix() == - domega_matrix_from_str(full_simplify_str(op_str))) - << '\n'; - } - - if (details) { - real_t scale = gmpf::pow(SQRT2, rz_approx.matrix().k()); - std::cerr << "angle = " << angle << '\n'; - std::cerr << rz_approx.matrix(); - std::cerr << "u decimal value = " - << "(" - << rz_approx.matrix().u().decimal().real() / scale - << "," - << rz_approx.matrix().u().decimal().imag() / scale - << ")" << '\n'; - std::cerr << "t decimal value = " - << "(" - << rz_approx.matrix().t().decimal().real() / scale - << "," - << rz_approx.matrix().t().decimal().imag() / scale - << ")" << '\n'; - std::cerr << "error = " << rz_approx.error() << '\n'; - str_t simplified = full_simplify_str(op_str); - std::string::difference_type n = - count(simplified.begin(), simplified.end(), 'T'); - std::cerr << "T count = " << n << '\n'; - std::cerr << "----" << '\n'; - } - - for (auto& ch : full_simplify_str(op_str)) { - std::cout << ch << " "; - } - std::cout << '\n'; + str_t op_str = synthesizer.get_rz_approx(real_t(angle)); + for (char c : op_str) { + std::cout << c << ' '; } + std::cout << '\n'; } } - - if (timer) { - std::cerr << "Duration = " << (static_cast(duration) / 1e6) - << '\n'; - } } diff --git a/tools/qasm_synth.cpp b/tools/qasm_synth.cpp index 1f16dcbd..988e7cb2 100644 --- a/tools/qasm_synth.cpp +++ b/tools/qasm_synth.cpp @@ -46,8 +46,6 @@ int main(int argc, char** argv) { CLI::App app{"Grid Synthesis rx/ry/rz substitution"}; - // this interface is more or less identical to that of grid_synth.cpp - // TODO: consider factoring out duplicated code? CLI::Option* prec_opt = app.add_option( "-p, --precision", prec, @@ -78,17 +76,18 @@ int main(int argc, char** argv) { CLI11_PARSE(app, argc, argv); - transformations::QASMSynthOptions options{ + GridSynthOptions opt{ prec, factor_effort, std::move(tablefile), (bool)*read, (bool)*write, check, details, verbose}; + MP_CONSTS = initialize_constants(opt.prec); auto program = parse_stdin("", true); // parse stdin using GMP if (program) { - transformations::qasm_synth(*program, options); + transformations::qasm_synth(*program, opt); std::cout << *program; } else { std::cerr << "Parsing failed\n"; - return 1; + return EXIT_FAILURE; } }