Loading mlir/parsers/openqasm/openqasm_mlir_generator.cpp +138 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,98 @@ static std::vector<std::string> search_for_inliner{ "u3", "u2", "u1", "cx", "id", "u0", "x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cz", "cy", "swap"}; static std::map<std::string, std::string> missing_builtins{ {"u", R"#( gate u(theta,phi,lambda) q { U(theta,phi,lambda) q; })#"}, {"p", R"#(gate p(theta) a { rz(theta) a; })#"}, {"sx", R"#(gate sx a { sdg a; h a; sdg a; })#"}, {"sxdg", R"#(gate sxdg a { s a; h a; s a; })#"}, {"cswap", R"#(gate cswap a,b,c { cx c,b; ccx a,b,c; cx c,b; })#"}, {"crx", R"#(gate crx(lambda) a,b { u1(pi/2) b; cx a,b; u3(-lambda/2,0,0) b; cx a,b; u3(lambda/2,-pi/2,0) b; })#"}, {"cry", R"#(gate cry(lambda) a,b { u3(lambda/2,0,0) b; cx a,b; u3(-lambda/2,0,0) b; cx a,b; ry(lambda) a; })#"}, {"cp", R"#(gate cp(lambda) a,b { p(lambda/2) a; cx a,b; p(-lambda/2) b; cx a,b; p(lambda/2) b; })#"}, {"csx", R"#(gate csx a,b { h b; cu1(pi/2) a,b; h b; })#"}, {"cu", R"#(gate cu(theta,phi,lambda,gamma) c, t { p(gamma) c; p((lambda+phi)/2) c; p((lambda-phi)/2) t; cx c,t; u(-theta/2,0,-(phi+lambda)/2) t; cx c,t; u(theta/2,phi,0) t; })#"}, {"rxx", R"#(gate rxx(theta) a,b { u3(pi/2, theta, 0) a; h b; cx a,b; u1(-theta) b; cx a,b; h b; u2(-pi, pi-theta) a; })#"}, {"rzz", R"#(gate rzz(theta) a,b { cx a,b; u1(theta) b; cx a,b; })#"}, {"rccx", R"#(gate rccx a,b,c { u2(0,pi) c; u1(pi/4) c; cx b, c; u1(-pi/4) c; cx a, c; u1(pi/4) c; cx b, c; u1(-pi/4) c; u2(0,pi) c; })#"}}; template <class Op> void split(const std::string &s, char delim, Op op) { std::stringstream ss(s); for (std::string item; std::getline(ss, item, delim);) { *op++ = item; } } inline std::vector<std::string> split(const std::string &s, char delim) { std::vector<std::string> elems; split(s, delim, std::back_inserter(elems)); return elems; } void CountGateDecls::visit(GateDecl &g) { auto name = g.id(); if (std::find(builtins.begin(), builtins.end(), name) == builtins.end()) { Loading Loading @@ -222,9 +314,54 @@ void OpenQasmMLIRGenerator::initialize_mlirgen(bool _add_entry_point, void OpenQasmMLIRGenerator::mlirgen(const std::string &src) { using namespace staq; std::string src_copy = src; // Make sure we have the preamble text std::string preamble = "OPENQASM 2.0;"; auto preamble_start = src.find(preamble); if (preamble_start == std::string::npos) { std::cout << "[OpenQASM MLIR Gen] Error, no OPENQASM 2.0 preamble text.\n"; exit(1); } preamble = "include \"qelib1.inc\";"; preamble_start = src.find(preamble); if (preamble_start == std::string::npos) { std::cout << "[OpenQASM MLIR Gen] Error, no include \"qelib1.inc\" " "preamble text.\n"; exit(1); } // Add any required missing pre-defines that we // know the impl for. std::vector<std::string> added; std::string extra_insts = "\n"; bool hasMeasures = false; auto lines = split(src, '\n'); for (auto line : lines) { if (line.find("OPENQASM") == std::string::npos && line.find("include") == std::string::npos && line.find("measure") == std::string::npos && line.find("qreg") == std::string::npos && line.find("creg") == std::string::npos) { auto inst_name = split(line, ' ')[0]; if (inst_name.find("(") != std::string::npos) { inst_name = inst_name.substr(0, inst_name.find("(")); } if (std::find(builtins.begin(), builtins.end(), inst_name) == builtins.end() && std::find(added.begin(), added.end(), inst_name) == added.end()) { extra_insts += missing_builtins[inst_name] + "\n"; added.push_back(inst_name); } } } src_copy.insert(preamble_start+preamble.length(), extra_insts); ast::ptr<ast::Program> prog; try { prog = parser::parse_string(src); prog = parser::parse_string(src_copy); // transformations::inline_ast(*prog); transformations::desugar(*prog); } catch (std::exception &e) { Loading mlir/qir_qrt/qir-qrt.cpp +29 −4 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include "xacc_service.hpp" #include "qcor_config.hpp" #include "xacc_config.hpp" #include "config_file_parser.hpp" Result ResultZero = 0; Result ResultOne = 1; Loading @@ -16,10 +17,11 @@ unsigned long allocated_qbits = 0; std::shared_ptr<xacc::AcceleratorBuffer> qbits; std::shared_ptr<xacc::Accelerator> qpu; std::string qpu_name = "qpp"; std::string qpu_config = ""; enum QRT_MODE { FTQC, NISQ }; QRT_MODE mode; std::vector<std::unique_ptr<Array>> allocated_arrays; int shots = 1024; int shots = 0; bool verbose = false; bool external_qreg_provided = false; Loading @@ -29,11 +31,13 @@ void print_help() { std::cout << "QCOR QIR Runtime Help Menu\n\n"; std::cout << "optional arguments:\n"; std::cout << " -qpu QPUNAME[:BACKEND] | example -qpu ibm:ibmq_vigo, -qpu aer:ibmq_vigo\n"; std::cout << " -qpu-config config_file.ini | example: -qpu ibm:ibmq_vigo -qpu-config ibm_config.ini\n"; std::cout << " -qrt QRT_MODE (can be nisq or ftqc) | example -qrt nisq\n"; std::cout << " -shots NUMSHOTS (number of shots to use in nisq run)\n"; std::cout << " -opt LEVEL | example -opt 1\n"; std::cout << " -print-opt-stats (turn on printout of optimization statistics) \n"; std::cout << " -v,-verbose,--verbose (run with printouts)\n\n"; std::cout << " -v,-verbose,--verbose (run with printouts)\n"; std::cout << " -xacc-verbose (turn on extra xacc verbose print-out)\n\n"; exit(0); } Loading @@ -46,10 +50,15 @@ void __quantum__rt__initialize(int argc, int8_t** argv) { auto arg = args[i]; if (arg == "-qpu") { qpu_name = args[i + 1]; } else if (arg == "-qpu-config") { qpu_config = args[i+1]; } else if (arg == "-qrt") { mode = args[i + 1] == "nisq" ? QRT_MODE::NISQ : QRT_MODE::FTQC; } else if (arg == "-shots") { shots = std::stoi(args[i + 1]); } else if (arg == "-xacc-verbose") { verbose = true; xacc::set_verbose(true); } else if (arg == "-v") { verbose = true; } else if (arg == "-verbose") { Loading Loading @@ -99,9 +108,20 @@ void initialize() { std::cout << "[qir-qrt] Running on " << qpu_name << " backend.\n"; std::shared_ptr<xacc::Accelerator> qpu; xacc::HeterogeneousMap qpu_config_map; if (!qpu_config.empty()) { auto parser = xacc::getService<xacc::ConfigFileParsingUtil>("ini"); qpu_config_map = parser->parse(qpu_config); } if (!qpu_config_map.keyExists<int>("shots") && shots > 0 && mode == QRT_MODE::NISQ) { if (verbose) printf("Automatically setting shots for nisq mode execution to %d\n", shots); qpu_config_map.insert("shots", shots); } if (mode == QRT_MODE::NISQ) { xacc::internal_compiler::__qrt_env = "nisq"; qpu = xacc::getAccelerator(qpu_name, {{"shots", shots}}); qpu = xacc::getAccelerator(qpu_name, qpu_config_map); } else { qpu = xacc::getAccelerator(qpu_name); } Loading Loading @@ -187,6 +207,11 @@ void __quantum__qis__rz(double x, Qubit* q) { if (verbose) printf("[qir-qrt] Applying Rz(%f) %lu\n", x, qcopy); ::quantum::rz({"q", qcopy}, x); } void __quantum__qis__u3(double theta, double phi, double lambda, Qubit* q) { std::size_t qcopy = reinterpret_cast<std::size_t>(q); if (verbose) printf("[qir-qrt] Applying U3(%f, %f, %f) %lu\n", theta, phi, lambda, qcopy); ::quantum::u3({"q", qcopy}, theta, phi, lambda); } Result* __quantum__qis__mz(Qubit* q) { if (verbose) Loading Loading @@ -240,7 +265,7 @@ void __quantum__rt__qubit_release_array(Array* q) { if (allocated_arrays[i].get() == q) { auto& array_ptr = allocated_arrays[i]; auto array_size = array_ptr->size(); if (verbose) if (verbose && mode == QRT_MODE::FTQC) printf("[qir-qrt] deallocating the qubit array of size %lu\n", array_size); for (int k = 0; k < array_size; k++) { Loading mlir/qir_qrt/qir-qrt.hpp +1 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ void __quantum__qis__z(Qubit* q); void __quantum__qis__rx(double x, Qubit* q); void __quantum__qis__ry(double x, Qubit* q); void __quantum__qis__rz(double x, Qubit* q); void __quantum__qis__u3(double theta, double phi, double lambda, Qubit* q); Result* __quantum__qis__mz(Qubit* q); Loading python/qcor.in.py +1 −0 Original line number Diff line number Diff line Loading @@ -696,6 +696,7 @@ class KernelBuilder(object): setattr(KernelBuilder, instruction[0].lower(), result[instruction[0].lower()]) def measure_all(self): self.qjit_str += '\n' self.qjit_str += self.TAB + 'for i in range({}.size()):\n'.format(self.qreg_name) self.qjit_str += self.TAB+self.TAB+'Measure({}[i])\n'.format(self.qreg_name) Loading tools/driver/qcor.in +8 −5 Original line number Diff line number Diff line Loading @@ -191,6 +191,9 @@ def main(argv=None): if '-qpu-config' in sys.argv[1:]: idx = sys.argv.index('-qpu-config') config_file = sys.argv[idx+1] if not os.path.exists(config_file): print('Invalid qpu config file path:', config_file) exit(1) accidx = sys.argv.index('-qpu') accName = sys.argv[accidx+1] Loading @@ -198,11 +201,9 @@ def main(argv=None): sys.argv.remove('-qpu') if config_file: # FIXME use absolute path name if ']' in accName: idx = accName.index(']') accName = accName[:idx] + ',qcor_qpu_config:'+config_file+accName[idx:] print(accName) accName = accName[:idx] + ',qcor_qpu_config:'+os.path.abspath(config_file)+accName[idx:] else: accName += '[qcor_qpu_config:'+config_file+']' sys.argv.remove(config_file) Loading Loading @@ -377,7 +378,9 @@ def main(argv=None): print(e.returncode) return e.returncode else: print('invalid command line arguments for qcor') print('invalid command line arguments for qcor:') print('source file name and type:', (None if filename == '' else filename), ',', (None if fileType == '' else fileType)) if verbose: print('current args: ', sys.argv) exit(1) else: # This is a .o file, so execute the link phase Loading Loading
mlir/parsers/openqasm/openqasm_mlir_generator.cpp +138 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,98 @@ static std::vector<std::string> search_for_inliner{ "u3", "u2", "u1", "cx", "id", "u0", "x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cz", "cy", "swap"}; static std::map<std::string, std::string> missing_builtins{ {"u", R"#( gate u(theta,phi,lambda) q { U(theta,phi,lambda) q; })#"}, {"p", R"#(gate p(theta) a { rz(theta) a; })#"}, {"sx", R"#(gate sx a { sdg a; h a; sdg a; })#"}, {"sxdg", R"#(gate sxdg a { s a; h a; s a; })#"}, {"cswap", R"#(gate cswap a,b,c { cx c,b; ccx a,b,c; cx c,b; })#"}, {"crx", R"#(gate crx(lambda) a,b { u1(pi/2) b; cx a,b; u3(-lambda/2,0,0) b; cx a,b; u3(lambda/2,-pi/2,0) b; })#"}, {"cry", R"#(gate cry(lambda) a,b { u3(lambda/2,0,0) b; cx a,b; u3(-lambda/2,0,0) b; cx a,b; ry(lambda) a; })#"}, {"cp", R"#(gate cp(lambda) a,b { p(lambda/2) a; cx a,b; p(-lambda/2) b; cx a,b; p(lambda/2) b; })#"}, {"csx", R"#(gate csx a,b { h b; cu1(pi/2) a,b; h b; })#"}, {"cu", R"#(gate cu(theta,phi,lambda,gamma) c, t { p(gamma) c; p((lambda+phi)/2) c; p((lambda-phi)/2) t; cx c,t; u(-theta/2,0,-(phi+lambda)/2) t; cx c,t; u(theta/2,phi,0) t; })#"}, {"rxx", R"#(gate rxx(theta) a,b { u3(pi/2, theta, 0) a; h b; cx a,b; u1(-theta) b; cx a,b; h b; u2(-pi, pi-theta) a; })#"}, {"rzz", R"#(gate rzz(theta) a,b { cx a,b; u1(theta) b; cx a,b; })#"}, {"rccx", R"#(gate rccx a,b,c { u2(0,pi) c; u1(pi/4) c; cx b, c; u1(-pi/4) c; cx a, c; u1(pi/4) c; cx b, c; u1(-pi/4) c; u2(0,pi) c; })#"}}; template <class Op> void split(const std::string &s, char delim, Op op) { std::stringstream ss(s); for (std::string item; std::getline(ss, item, delim);) { *op++ = item; } } inline std::vector<std::string> split(const std::string &s, char delim) { std::vector<std::string> elems; split(s, delim, std::back_inserter(elems)); return elems; } void CountGateDecls::visit(GateDecl &g) { auto name = g.id(); if (std::find(builtins.begin(), builtins.end(), name) == builtins.end()) { Loading Loading @@ -222,9 +314,54 @@ void OpenQasmMLIRGenerator::initialize_mlirgen(bool _add_entry_point, void OpenQasmMLIRGenerator::mlirgen(const std::string &src) { using namespace staq; std::string src_copy = src; // Make sure we have the preamble text std::string preamble = "OPENQASM 2.0;"; auto preamble_start = src.find(preamble); if (preamble_start == std::string::npos) { std::cout << "[OpenQASM MLIR Gen] Error, no OPENQASM 2.0 preamble text.\n"; exit(1); } preamble = "include \"qelib1.inc\";"; preamble_start = src.find(preamble); if (preamble_start == std::string::npos) { std::cout << "[OpenQASM MLIR Gen] Error, no include \"qelib1.inc\" " "preamble text.\n"; exit(1); } // Add any required missing pre-defines that we // know the impl for. std::vector<std::string> added; std::string extra_insts = "\n"; bool hasMeasures = false; auto lines = split(src, '\n'); for (auto line : lines) { if (line.find("OPENQASM") == std::string::npos && line.find("include") == std::string::npos && line.find("measure") == std::string::npos && line.find("qreg") == std::string::npos && line.find("creg") == std::string::npos) { auto inst_name = split(line, ' ')[0]; if (inst_name.find("(") != std::string::npos) { inst_name = inst_name.substr(0, inst_name.find("(")); } if (std::find(builtins.begin(), builtins.end(), inst_name) == builtins.end() && std::find(added.begin(), added.end(), inst_name) == added.end()) { extra_insts += missing_builtins[inst_name] + "\n"; added.push_back(inst_name); } } } src_copy.insert(preamble_start+preamble.length(), extra_insts); ast::ptr<ast::Program> prog; try { prog = parser::parse_string(src); prog = parser::parse_string(src_copy); // transformations::inline_ast(*prog); transformations::desugar(*prog); } catch (std::exception &e) { Loading
mlir/qir_qrt/qir-qrt.cpp +29 −4 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include "xacc_service.hpp" #include "qcor_config.hpp" #include "xacc_config.hpp" #include "config_file_parser.hpp" Result ResultZero = 0; Result ResultOne = 1; Loading @@ -16,10 +17,11 @@ unsigned long allocated_qbits = 0; std::shared_ptr<xacc::AcceleratorBuffer> qbits; std::shared_ptr<xacc::Accelerator> qpu; std::string qpu_name = "qpp"; std::string qpu_config = ""; enum QRT_MODE { FTQC, NISQ }; QRT_MODE mode; std::vector<std::unique_ptr<Array>> allocated_arrays; int shots = 1024; int shots = 0; bool verbose = false; bool external_qreg_provided = false; Loading @@ -29,11 +31,13 @@ void print_help() { std::cout << "QCOR QIR Runtime Help Menu\n\n"; std::cout << "optional arguments:\n"; std::cout << " -qpu QPUNAME[:BACKEND] | example -qpu ibm:ibmq_vigo, -qpu aer:ibmq_vigo\n"; std::cout << " -qpu-config config_file.ini | example: -qpu ibm:ibmq_vigo -qpu-config ibm_config.ini\n"; std::cout << " -qrt QRT_MODE (can be nisq or ftqc) | example -qrt nisq\n"; std::cout << " -shots NUMSHOTS (number of shots to use in nisq run)\n"; std::cout << " -opt LEVEL | example -opt 1\n"; std::cout << " -print-opt-stats (turn on printout of optimization statistics) \n"; std::cout << " -v,-verbose,--verbose (run with printouts)\n\n"; std::cout << " -v,-verbose,--verbose (run with printouts)\n"; std::cout << " -xacc-verbose (turn on extra xacc verbose print-out)\n\n"; exit(0); } Loading @@ -46,10 +50,15 @@ void __quantum__rt__initialize(int argc, int8_t** argv) { auto arg = args[i]; if (arg == "-qpu") { qpu_name = args[i + 1]; } else if (arg == "-qpu-config") { qpu_config = args[i+1]; } else if (arg == "-qrt") { mode = args[i + 1] == "nisq" ? QRT_MODE::NISQ : QRT_MODE::FTQC; } else if (arg == "-shots") { shots = std::stoi(args[i + 1]); } else if (arg == "-xacc-verbose") { verbose = true; xacc::set_verbose(true); } else if (arg == "-v") { verbose = true; } else if (arg == "-verbose") { Loading Loading @@ -99,9 +108,20 @@ void initialize() { std::cout << "[qir-qrt] Running on " << qpu_name << " backend.\n"; std::shared_ptr<xacc::Accelerator> qpu; xacc::HeterogeneousMap qpu_config_map; if (!qpu_config.empty()) { auto parser = xacc::getService<xacc::ConfigFileParsingUtil>("ini"); qpu_config_map = parser->parse(qpu_config); } if (!qpu_config_map.keyExists<int>("shots") && shots > 0 && mode == QRT_MODE::NISQ) { if (verbose) printf("Automatically setting shots for nisq mode execution to %d\n", shots); qpu_config_map.insert("shots", shots); } if (mode == QRT_MODE::NISQ) { xacc::internal_compiler::__qrt_env = "nisq"; qpu = xacc::getAccelerator(qpu_name, {{"shots", shots}}); qpu = xacc::getAccelerator(qpu_name, qpu_config_map); } else { qpu = xacc::getAccelerator(qpu_name); } Loading Loading @@ -187,6 +207,11 @@ void __quantum__qis__rz(double x, Qubit* q) { if (verbose) printf("[qir-qrt] Applying Rz(%f) %lu\n", x, qcopy); ::quantum::rz({"q", qcopy}, x); } void __quantum__qis__u3(double theta, double phi, double lambda, Qubit* q) { std::size_t qcopy = reinterpret_cast<std::size_t>(q); if (verbose) printf("[qir-qrt] Applying U3(%f, %f, %f) %lu\n", theta, phi, lambda, qcopy); ::quantum::u3({"q", qcopy}, theta, phi, lambda); } Result* __quantum__qis__mz(Qubit* q) { if (verbose) Loading Loading @@ -240,7 +265,7 @@ void __quantum__rt__qubit_release_array(Array* q) { if (allocated_arrays[i].get() == q) { auto& array_ptr = allocated_arrays[i]; auto array_size = array_ptr->size(); if (verbose) if (verbose && mode == QRT_MODE::FTQC) printf("[qir-qrt] deallocating the qubit array of size %lu\n", array_size); for (int k = 0; k < array_size; k++) { Loading
mlir/qir_qrt/qir-qrt.hpp +1 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ void __quantum__qis__z(Qubit* q); void __quantum__qis__rx(double x, Qubit* q); void __quantum__qis__ry(double x, Qubit* q); void __quantum__qis__rz(double x, Qubit* q); void __quantum__qis__u3(double theta, double phi, double lambda, Qubit* q); Result* __quantum__qis__mz(Qubit* q); Loading
python/qcor.in.py +1 −0 Original line number Diff line number Diff line Loading @@ -696,6 +696,7 @@ class KernelBuilder(object): setattr(KernelBuilder, instruction[0].lower(), result[instruction[0].lower()]) def measure_all(self): self.qjit_str += '\n' self.qjit_str += self.TAB + 'for i in range({}.size()):\n'.format(self.qreg_name) self.qjit_str += self.TAB+self.TAB+'Measure({}[i])\n'.format(self.qreg_name) Loading
tools/driver/qcor.in +8 −5 Original line number Diff line number Diff line Loading @@ -191,6 +191,9 @@ def main(argv=None): if '-qpu-config' in sys.argv[1:]: idx = sys.argv.index('-qpu-config') config_file = sys.argv[idx+1] if not os.path.exists(config_file): print('Invalid qpu config file path:', config_file) exit(1) accidx = sys.argv.index('-qpu') accName = sys.argv[accidx+1] Loading @@ -198,11 +201,9 @@ def main(argv=None): sys.argv.remove('-qpu') if config_file: # FIXME use absolute path name if ']' in accName: idx = accName.index(']') accName = accName[:idx] + ',qcor_qpu_config:'+config_file+accName[idx:] print(accName) accName = accName[:idx] + ',qcor_qpu_config:'+os.path.abspath(config_file)+accName[idx:] else: accName += '[qcor_qpu_config:'+config_file+']' sys.argv.remove(config_file) Loading Loading @@ -377,7 +378,9 @@ def main(argv=None): print(e.returncode) return e.returncode else: print('invalid command line arguments for qcor') print('invalid command line arguments for qcor:') print('source file name and type:', (None if filename == '' else filename), ',', (None if fileType == '' else fileType)) if verbose: print('current args: ', sys.argv) exit(1) else: # This is a .o file, so execute the link phase Loading