Loading mlir/qir_qrt/qir-qrt.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -523,6 +523,9 @@ void __quantum__rt__finalize() { xacc::internal_compiler::execute_pass_manager(); ::quantum::submit(global_qreg.get()); } // QRT finalization ::quantum::finalize(); } bool __quantum__rt__result_equal(Result *res, Result *comp) { Loading runtime/qrt/impls/ftqc/CMakeLists.txt +1 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ # *******************************************************************************/ set(LIBRARY_NAME qcor-ftqc-qrt) file(GLOB SRC *.cpp) file(GLOB SRC *.cpp tracer/*.cpp) usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC) usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC) Loading runtime/qrt/impls/ftqc/ftqc_qrt.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include "xacc.hpp" #include "xacc_internal_compiler.hpp" #include "xacc_service.hpp" #include "tracer/ResourcesTracerAccelerator.hpp" using namespace cppmicroservices; namespace { Loading Loading @@ -279,6 +280,13 @@ private: } } virtual void finalize() override { if (std::dynamic_pointer_cast<qcor::TracerAccelerator>(qpu)) { std::dynamic_pointer_cast<qcor::TracerAccelerator>(qpu) ->printResourcesEstimationReport(); } } private: bool mark_as_compute = false; // Are we in a instruction collection mode? Loading @@ -302,6 +310,8 @@ public: void Start(BundleContext context) { auto xt = std::make_shared<qcor::FTQC>(); context.RegisterService<quantum::QuantumRuntime>(xt); context.RegisterService<xacc::Accelerator>( std::make_shared<qcor::TracerAccelerator>()); } void Stop(BundleContext /*context*/) {} }; Loading runtime/qrt/impls/ftqc/tracer/ResourcesTracerAccelerator.cpp 0 → 100644 +90 −0 Original line number Diff line number Diff line #include "ResourcesTracerAccelerator.hpp" #include <iomanip> #include <random> using namespace xacc; namespace qcor { void TracerAccelerator::initialize(const HeterogeneousMap ¶ms) { qubitIdToMeasureProbs.clear(); if (params.keyExists<std::vector<double>>("meas1-probs")) { const auto meas1Probs = params.get<std::vector<double>>("meas1-probs"); for (size_t i = 0; i < meas1Probs.size(); ++i) { if (meas1Probs[i] < 0.0 || meas1Probs[i] > 1.0) { xacc::error("Invalid measure probability setting: " + std::to_string(meas1Probs[i])); } qubitIdToMeasureProbs[i] = meas1Probs[i]; } } } // For NISQ: resource estimation is simply printing out the circuit.... void TracerAccelerator::execute( std::shared_ptr<AcceleratorBuffer> buffer, const std::shared_ptr<CompositeInstruction> compositeInstruction) { xacc::error("Unsupported!!!"); } void TracerAccelerator::execute( std::shared_ptr<AcceleratorBuffer> buffer, const std::vector<std::shared_ptr<CompositeInstruction>> compositeInstructions) { xacc::error("Unsupported!!!"); } void TracerAccelerator::apply(std::shared_ptr<AcceleratorBuffer> buffer, std::shared_ptr<Instruction> inst) { for (const auto &bitId : inst->bits()) { qubit_idxs.emplace(bitId); } if (gateNameToCount.find(inst->name()) == gateNameToCount.end()) { gateNameToCount[inst->name()] = 1; } else { gateNameToCount[inst->name()] += 1; } // Emulate measure: if (inst->name() == "Measure") { const double meas1Prob = getMeas1Prob(inst->bits()[0]); static const auto generateRan = []() { std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(0, 1); return dis(gen); }; // meas1Prob = 1.0 => always returns true // meas1Prob = 0.0 => always returns false const auto measRes = generateRan() < meas1Prob; buffer->measure(inst->bits()[0], (measRes ? 1 : 0)); } } void TracerAccelerator::printResourcesEstimationReport() { // Print resources estimation result: // Currently, simply print gate count: std::cout << "Resources Estimation Result:\n"; std::cout << "Number of qubit required: " << qubit_idxs.size() << "\n"; std::cout << "Gate Count Report: \n"; size_t totalNumberGates = 0; std::stringstream stream; const size_t nbColumns = 2; const size_t columnWidth = 8; const auto totalWidth = nbColumns * columnWidth + 6; stream << std::string(totalWidth, '-') << "\n"; stream << "| " << std::left << std::setw(8) << "GATE" << " |"; stream << std::left << std::setw(8) << "COUNT" << " |\n"; stream << std::string(totalWidth, '-') << "\n"; const auto printEachRow = [&](const std::string &gateName, int count) { stream << "| " << std::setw(8) << gateName << " |"; stream << std::setw(8) << count << " |\n"; }; for (const auto &[gateName, count] : gateNameToCount) { printEachRow(gateName, count); } stream << std::string(totalWidth, '-') << "\n"; std::cout << stream.str(); } } // namespace qcor runtime/qrt/impls/ftqc/tracer/ResourcesTracerAccelerator.hpp 0 → 100644 +60 −0 Original line number Diff line number Diff line #pragma one #include "xacc.hpp" namespace qcor { // Descriptions: // The TracerAccelerator estimates resources (gate counts, qubits) of a quantum // program by emulating execution the quantum program (not static analysis). The // idea is to collect/trace a set of metrics during the execution. Measurement // results can be emulated in different modes: (1) Fixed 0 or 1. (2) Random with // provided probability threshold. i.e., users can run multiple randomized // tracing runs to compute the upper bound estimate of resources. This provides // similar functionalities as the QDK resources estimator // https://docs.microsoft.com/en-us/azure/quantum/user-guide/machines/resources-estimator class TracerAccelerator : public xacc::Accelerator { public: // Identifiable interface impls virtual const std::string name() const override { return "tracer"; } virtual const std::string description() const override { return ""; } // Accelerator interface impls virtual void initialize(const xacc::HeterogeneousMap ¶ms = {}) override; virtual void updateConfiguration(const xacc::HeterogeneousMap &config) override { initialize(config); }; virtual const std::vector<std::string> configurationKeys() override { return {}; } virtual xacc::HeterogeneousMap getProperties() override { return {}; } virtual void execute(std::shared_ptr<xacc::AcceleratorBuffer> buffer, const std::shared_ptr<xacc::CompositeInstruction> compositeInstruction) override; virtual void execute(std::shared_ptr<xacc::AcceleratorBuffer> buffer, const std::vector<std::shared_ptr<xacc::CompositeInstruction>> compositeInstructions) override; virtual void apply(std::shared_ptr<xacc::AcceleratorBuffer> buffer, std::shared_ptr<xacc::Instruction> inst) override; void printResourcesEstimationReport(); private: // Probability to measure 1: std::unordered_map<size_t, double> qubitIdToMeasureProbs; double getMeas1Prob(size_t bitIdx) { if (qubitIdToMeasureProbs.find(bitIdx) == qubitIdToMeasureProbs.end()) { // Default measurement = 0 => prob gets 1 == 0.0 return 0.0; } else { // There is custom measurement probability setting for this qubit. return qubitIdToMeasureProbs[bitIdx]; } } std::set<size_t> qubit_idxs; // Resources metric // Gate name to count std::unordered_map<std::string, size_t> gateNameToCount; // TODO: // - We could in-principle perform gate layering during tracing // i.e., gates on non-overlapping qubits. // => add a circuit depth metric // - Number of ancilla allocations, etc. }; } // namespace qcor No newline at end of file Loading
mlir/qir_qrt/qir-qrt.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -523,6 +523,9 @@ void __quantum__rt__finalize() { xacc::internal_compiler::execute_pass_manager(); ::quantum::submit(global_qreg.get()); } // QRT finalization ::quantum::finalize(); } bool __quantum__rt__result_equal(Result *res, Result *comp) { Loading
runtime/qrt/impls/ftqc/CMakeLists.txt +1 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ # *******************************************************************************/ set(LIBRARY_NAME qcor-ftqc-qrt) file(GLOB SRC *.cpp) file(GLOB SRC *.cpp tracer/*.cpp) usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC) usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC) Loading
runtime/qrt/impls/ftqc/ftqc_qrt.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include "xacc.hpp" #include "xacc_internal_compiler.hpp" #include "xacc_service.hpp" #include "tracer/ResourcesTracerAccelerator.hpp" using namespace cppmicroservices; namespace { Loading Loading @@ -279,6 +280,13 @@ private: } } virtual void finalize() override { if (std::dynamic_pointer_cast<qcor::TracerAccelerator>(qpu)) { std::dynamic_pointer_cast<qcor::TracerAccelerator>(qpu) ->printResourcesEstimationReport(); } } private: bool mark_as_compute = false; // Are we in a instruction collection mode? Loading @@ -302,6 +310,8 @@ public: void Start(BundleContext context) { auto xt = std::make_shared<qcor::FTQC>(); context.RegisterService<quantum::QuantumRuntime>(xt); context.RegisterService<xacc::Accelerator>( std::make_shared<qcor::TracerAccelerator>()); } void Stop(BundleContext /*context*/) {} }; Loading
runtime/qrt/impls/ftqc/tracer/ResourcesTracerAccelerator.cpp 0 → 100644 +90 −0 Original line number Diff line number Diff line #include "ResourcesTracerAccelerator.hpp" #include <iomanip> #include <random> using namespace xacc; namespace qcor { void TracerAccelerator::initialize(const HeterogeneousMap ¶ms) { qubitIdToMeasureProbs.clear(); if (params.keyExists<std::vector<double>>("meas1-probs")) { const auto meas1Probs = params.get<std::vector<double>>("meas1-probs"); for (size_t i = 0; i < meas1Probs.size(); ++i) { if (meas1Probs[i] < 0.0 || meas1Probs[i] > 1.0) { xacc::error("Invalid measure probability setting: " + std::to_string(meas1Probs[i])); } qubitIdToMeasureProbs[i] = meas1Probs[i]; } } } // For NISQ: resource estimation is simply printing out the circuit.... void TracerAccelerator::execute( std::shared_ptr<AcceleratorBuffer> buffer, const std::shared_ptr<CompositeInstruction> compositeInstruction) { xacc::error("Unsupported!!!"); } void TracerAccelerator::execute( std::shared_ptr<AcceleratorBuffer> buffer, const std::vector<std::shared_ptr<CompositeInstruction>> compositeInstructions) { xacc::error("Unsupported!!!"); } void TracerAccelerator::apply(std::shared_ptr<AcceleratorBuffer> buffer, std::shared_ptr<Instruction> inst) { for (const auto &bitId : inst->bits()) { qubit_idxs.emplace(bitId); } if (gateNameToCount.find(inst->name()) == gateNameToCount.end()) { gateNameToCount[inst->name()] = 1; } else { gateNameToCount[inst->name()] += 1; } // Emulate measure: if (inst->name() == "Measure") { const double meas1Prob = getMeas1Prob(inst->bits()[0]); static const auto generateRan = []() { std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(0, 1); return dis(gen); }; // meas1Prob = 1.0 => always returns true // meas1Prob = 0.0 => always returns false const auto measRes = generateRan() < meas1Prob; buffer->measure(inst->bits()[0], (measRes ? 1 : 0)); } } void TracerAccelerator::printResourcesEstimationReport() { // Print resources estimation result: // Currently, simply print gate count: std::cout << "Resources Estimation Result:\n"; std::cout << "Number of qubit required: " << qubit_idxs.size() << "\n"; std::cout << "Gate Count Report: \n"; size_t totalNumberGates = 0; std::stringstream stream; const size_t nbColumns = 2; const size_t columnWidth = 8; const auto totalWidth = nbColumns * columnWidth + 6; stream << std::string(totalWidth, '-') << "\n"; stream << "| " << std::left << std::setw(8) << "GATE" << " |"; stream << std::left << std::setw(8) << "COUNT" << " |\n"; stream << std::string(totalWidth, '-') << "\n"; const auto printEachRow = [&](const std::string &gateName, int count) { stream << "| " << std::setw(8) << gateName << " |"; stream << std::setw(8) << count << " |\n"; }; for (const auto &[gateName, count] : gateNameToCount) { printEachRow(gateName, count); } stream << std::string(totalWidth, '-') << "\n"; std::cout << stream.str(); } } // namespace qcor
runtime/qrt/impls/ftqc/tracer/ResourcesTracerAccelerator.hpp 0 → 100644 +60 −0 Original line number Diff line number Diff line #pragma one #include "xacc.hpp" namespace qcor { // Descriptions: // The TracerAccelerator estimates resources (gate counts, qubits) of a quantum // program by emulating execution the quantum program (not static analysis). The // idea is to collect/trace a set of metrics during the execution. Measurement // results can be emulated in different modes: (1) Fixed 0 or 1. (2) Random with // provided probability threshold. i.e., users can run multiple randomized // tracing runs to compute the upper bound estimate of resources. This provides // similar functionalities as the QDK resources estimator // https://docs.microsoft.com/en-us/azure/quantum/user-guide/machines/resources-estimator class TracerAccelerator : public xacc::Accelerator { public: // Identifiable interface impls virtual const std::string name() const override { return "tracer"; } virtual const std::string description() const override { return ""; } // Accelerator interface impls virtual void initialize(const xacc::HeterogeneousMap ¶ms = {}) override; virtual void updateConfiguration(const xacc::HeterogeneousMap &config) override { initialize(config); }; virtual const std::vector<std::string> configurationKeys() override { return {}; } virtual xacc::HeterogeneousMap getProperties() override { return {}; } virtual void execute(std::shared_ptr<xacc::AcceleratorBuffer> buffer, const std::shared_ptr<xacc::CompositeInstruction> compositeInstruction) override; virtual void execute(std::shared_ptr<xacc::AcceleratorBuffer> buffer, const std::vector<std::shared_ptr<xacc::CompositeInstruction>> compositeInstructions) override; virtual void apply(std::shared_ptr<xacc::AcceleratorBuffer> buffer, std::shared_ptr<xacc::Instruction> inst) override; void printResourcesEstimationReport(); private: // Probability to measure 1: std::unordered_map<size_t, double> qubitIdToMeasureProbs; double getMeas1Prob(size_t bitIdx) { if (qubitIdToMeasureProbs.find(bitIdx) == qubitIdToMeasureProbs.end()) { // Default measurement = 0 => prob gets 1 == 0.0 return 0.0; } else { // There is custom measurement probability setting for this qubit. return qubitIdToMeasureProbs[bitIdx]; } } std::set<size_t> qubit_idxs; // Resources metric // Gate name to count std::unordered_map<std::string, size_t> gateNameToCount; // TODO: // - We could in-principle perform gate layering during tracing // i.e., gates on non-overlapping qubits. // => add a circuit depth metric // - Number of ancilla allocations, etc. }; } // namespace qcor No newline at end of file