diff --git a/cmake/Findbackends.cmake b/cmake/Findbackends.cmake new file mode 100644 index 0000000..6dc77f2 --- /dev/null +++ b/cmake/Findbackends.cmake @@ -0,0 +1,13 @@ +include(FetchContent) + +FetchContent_Declare( + backends + GIT_REPOSITORY git@github.com:Munich-Quantum-Software-Stack/backends.git + GIT_TAG cmake-install +) + +FetchContent_MakeAvailable(backends) +# FetchContent_GetProperties(qdmi) + +# set(QDMI_INCLUDE_DIRS "${qdmi_SOURCE_DIR}/include") +# set(QDMI_SRC_DIRS "${qdmi_SOURCE_DIR}/src") \ No newline at end of file diff --git a/cmake/Findqinfo.cmake b/cmake/Findqinfo.cmake new file mode 100644 index 0000000..c32c398 --- /dev/null +++ b/cmake/Findqinfo.cmake @@ -0,0 +1,9 @@ +include(FetchContent) + +FetchContent_Declare( + qinfo + GIT_REPOSITORY git@github.com:Munich-Quantum-Software-Stack/QInfo.git + GIT_TAG testing +) + +FetchContent_MakeAvailable(qinfo) diff --git a/docs/Concept.md b/docs/Concept.md index 510bd4c..c905610 100644 --- a/docs/Concept.md +++ b/docs/Concept.md @@ -160,7 +160,7 @@ The set of Data Paths forms a Data-path Graph. Each Data Path has a **source** and a **target Component**, but apart from that, no other rules apply. Data Paths may be oriented (differentiating between the source and the target) or bidirectional. There may also be multiple Data Paths connecting the same pair of Components, enabling the representation of multiple dependencies or relationships. -To differentiate between these, attribute ‘dp_type’ is used to easily group or tell apart different kinds of information carried by Data Paths. +To differentiate between these, attribute ‘type’ is used to easily group or tell apart different kinds of information carried by Data Paths. Analogously to Components, Data Paths have a set of default properties, such as bandwidth or latency, and an std::map **attrib**, where arbitrary information can be attached. Data Paths may carry all different kinds of information, including but not limited to performance-related or power consumption-related information, or even application-specific data diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 16a3971..98d7ede 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -18,6 +18,7 @@ add_executable(larger_topo larger_topo.cpp) add_executable(sys-sage-benchmarking sys-sage-benchmarking.cpp) add_executable(use_custom_parser custom_parser_musa/use_custom_parser.cpp custom_parser_musa/musa_parser.cpp custom_parser_musa/musa_parser.hpp) add_executable(cccbenchplushwloc cccbenchplushwloc.cpp) +add_executable(qdmi-test qdmi-test.cpp) install(TARGETS basic_usage mt4g-parser custom_attributes larger_topo sys-sage-benchmarking use_custom_parser cccbenchplushwloc DESTINATION bin/examples) install(DIRECTORY example_data DESTINATION bin/examples) @@ -38,3 +39,8 @@ if(NVIDIA_MIG) add_executable(nvidia-mig nvidia-mig.cpp) install(TARGETS nvidia-mig DESTINATION bin/examples) endif() + +target_link_libraries(qdmi-test PRIVATE + qdmi + qinfo + ) \ No newline at end of file diff --git a/examples/qdmi-test.cpp b/examples/qdmi-test.cpp new file mode 100644 index 0000000..3c68968 --- /dev/null +++ b/examples/qdmi-test.cpp @@ -0,0 +1,139 @@ +/* Possible exports +export CPATH=$CPATH:/home/diogenes/sys-sage/build/_deps/qinfo-src/include/ +export CPATH=$CPATH:/home/diogenes/sys-sage/build/_deps/qdmi-src/include +export CONF_IBM=/home/diogenes/sys-sage/build/_deps/backends-src/tests/ibm_conf.json +export QDMI_CONFIG_FILE=/home/diogenes/sys-sage/build/_deps/qdmi-src/.qdmi-config +export PROP_IBM=/home/diogenes/sys-sage/build/_deps/backends-src/tests/ibm_prob.json +*/ + +#include +#include +#include +#include "sys-sage.hpp" + +int main() +{ + std::cout << std::setprecision(15); + // Create an instance of the interface + // To-Do: Consider QdmiParser as a static class + QdmiParser qdmi; + + // Use QdmiParser to create the topology of either all the backends or one of the backends + /*******************************************Method 1**********************************************/ + + Topology* qc_topo = new Topology(); + qdmi.createAllQcTopo(qc_topo); + + cout << "---------------- Printing the configuration of IBM Backend----------------" << endl; + qc_topo->PrintSubtree(); + cout << "---------------- Printing Qubit Coupling Mappings for IBM Backend----------------" << endl; + QuantumBackend* qc = dynamic_cast(qc_topo->GetChild(0)); + int total_qubits = qc->CountAllSubcomponents(); + for (int i = 0; i < total_qubits; i++) + { + Qubit* q = dynamic_cast(qc->GetChild(i)); + std::cout << "Qubit " << i << " has coupling map { "; + auto coupling_map = q->GetCouplingMapping(); + for (long unsigned j = 0; j < coupling_map.size(); j++) + { + std::cout << coupling_map[j] << " "; + } + std::cout << "}\n"; + } + cout << "---------------- Printing Supported Gate Types for IBM Backend----------------" << endl; + auto _1q_gates = qc->GetGatesBySize(SYS_SAGE_1Q_QUANTUM_GATE); + auto _2q_gates = qc->GetGatesBySize(SYS_SAGE_2Q_QUANTUM_GATE); + auto _mq_gates = qc->GetGatesBySize(SYS_SAGE_MQ_QUANTUM_GATE); + auto _0q_gates = qc->GetGatesBySize(SYS_SAGE_NO_TYPE_QUANTUM_GATE); + + if(_1q_gates.size()) + { + int size = _1q_gates.size(); + std::cout << "Total " << size << " 1-Qubit gate(s)\n"; + for (int i = 0; i < size; ++i) + { + std::cout << "Gate name:" << _1q_gates[i]->GetName() << ", "; + std::cout << "Gate size:" << _1q_gates[i]->GetGateSize() << ", "; + std::cout << "Gate fidelity:" << _1q_gates[i]->GetFidelity() << "\n"; + } + + } + if(_2q_gates.size()) + { + int size = _2q_gates.size(); + std::cout << "Total " << size << " 2-Qubit gate(s)\n"; + for (int i = 0; i < size; ++i) + { + std::cout << " Gate name:" << _2q_gates[i]->GetName() << ", "; + std::cout << "Gate size:" << _2q_gates[i]->GetGateSize() << ", "; + std::cout << "Gate fidelity:" << _2q_gates[i]->GetFidelity() << "\n"; + } + + } + if(_mq_gates.size()) + { + int size = _mq_gates.size(); + std::cout << "Total " << size << " M-Qubit gate(s)\n"; + for (int i = 0; i < size; ++i) + { + std::cout << " Gate name:" << _mq_gates[i]->GetName() << ", "; + std::cout << "Gate size:" << _mq_gates[i]->GetGateSize() << ", "; + std::cout << "Gate fidelity:" << _mq_gates[i]->GetFidelity() << "\n"; + } + + } + if(_0q_gates.size()) + { + int size = _0q_gates.size(); + std::cout << "Total " << size << " gate(s) with no type\n"; + for (int i = 0; i < size; ++i) + { + std::cout << " Gate name:" << _0q_gates[i]->GetName() << ", "; + std::cout << "Gate size:" << _0q_gates[i]->GetGateSize() << ", "; + std::cout << "Gate fidelity:" << _0q_gates[i]->GetFidelity() << "\n"; + } + + } + + std::cout << "---------------- Printing Qubit Properties for IBM Backend----------------" << endl; + for (int i = 0; i < total_qubits; i++) + { + Qubit* q = dynamic_cast(qc->GetChild(i)); + std::cout << "Qubit " << i << " has following properties: \n"; + std::cout << " T1: " << q->GetT1() << "\n"; + std::cout << " T2: " << q->GetT2() << "\n"; + std::cout << " Readout Error: " << q->GetReadoutError() << "\n"; + std::cout << " Readout Length: " << q->GetReadoutLength() << "\n"; + } + + std::cout << "---------------- Printing Coupling Maps of all the Qubits----------------" << endl; + auto children = qc->GetAllCouplingMaps(); + for (auto it = children.begin(); it != children.end(); ++it) { + std::cout << "{" << it->first << ", " << it->second << "}\n"; + } + + + /*******************************************Method 2**********************************************/ + // auto quantum_backends = qdmi.get_available_backends(); + // std::cout << "Total " << quantum_backends.size() << " devices found.\n"; + // QuantumBackend* qc_topo = new QuantumBackend(0, ""); + // qdmi.createQcTopo(qc_topo, quantum_backends[0]); + + // cout << "---------------- Printing the configuration of QLM Backend ----------------" << endl; + // qc_topo->PrintSubtree(); + // cout << "---------------- Printing Qubit Coupling Mappings of QLM Backend----------------" << endl; + // int total_qubits = qc_topo->CountAllSubcomponents(); + // for (int i = 0; i < total_qubits; i++) + // { + // Qubit* q = dynamic_cast(qc_topo->GetChild(i)); + // std::cout << "Qubit " << i << " has coupling map { "; + // auto coupling_map = q->GetCouplingMapping(); + // for (long unsigned j = 0; j < coupling_map.size(); j++) + // { + // std::cout << coupling_map[j] << " "; + // } + // std::cout << "}\n"; + // } + + return 0; +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0d3341e..79aeff7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake" ${CMAKE_MODULE_PATH}) #defines.hpp header with #cmakedefine configure_file(${PROJECT_SOURCE_DIR}/src/defines.hpp.in ${PROJECT_SOURCE_DIR}/src/defines.hpp) @@ -17,6 +18,7 @@ set(SOURCES parsers/caps-numa-benchmark.cpp parsers/mt4g.cpp parsers/cccbench.cpp + parsers/qdmi-parser.cpp ) set(HEADERS @@ -29,25 +31,45 @@ set(HEADERS parsers/caps-numa-benchmark.hpp parsers/mt4g.hpp parsers/cccbench.cpp + parsers/qdmi-parser.hpp ) add_library(sys-sage SHARED ${SOURCES} ${HEADERS}) -target_include_directories(sys-sage PUBLIC - $ - $ - $ +# For Quantum Systems +# Find QDMI package +find_package(backends REQUIRED) + +# Find QInfo package +find_package(qinfo REQUIRED) + +# Find nlohmann_json package +find_package(nlohmann_json REQUIRED) + +target_link_libraries(sys-sage PUBLIC + backend_ibm + qdmi + qinfo + nlohmann_json::nlohmann_json + ) + + +target_include_directories(sys-sage + PUBLIC $ + $ + $ ) + install( TARGETS sys-sage - EXPORT sys-sage-targets + EXPORT sys-sage-targets RUNTIME DESTINATION bin LIBRARY DESTINATION lib/cmake/lib ARCHIVE DESTINATION lib/cmake/lib ) #for spack install( - EXPORT sys-sage-targets + EXPORT sys-sage-targets FILE sys-sage-targets.cmake DESTINATION lib/cmake/sys-sage NAMESPACE sys-sage:: @@ -65,3 +87,5 @@ install( install(DIRECTORY "." DESTINATION inc FILES_MATCHING PATTERN "*.hpp") + +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) \ No newline at end of file diff --git a/src/Component.cpp b/src/Component.cpp index 4b4296e..eb48f52 100644 --- a/src/Component.cpp +++ b/src/Component.cpp @@ -447,6 +447,11 @@ string Component::GetComponentTypeStr() return "Node"; case SYS_SAGE_COMPONENT_TOPOLOGY: return "Topology"; + case SYS_SAGE_COMPONENT_QUANTUM_BACKEND: + return "Quantum Backend"; + case SYS_SAGE_COMPONENT_QUBIT: + return "Qubit"; + } return ""; } @@ -731,3 +736,118 @@ Core::Core(Component * parent, int _id, string _name):Component(parent, _id, _na Thread::Thread(int _id, string _name):Component(_id, _name, SYS_SAGE_COMPONENT_THREAD){} Thread::Thread(Component * parent, int _id, string _name):Component(parent, _id, _name, SYS_SAGE_COMPONENT_THREAD){} + +QuantumBackend::QuantumBackend(int _id, string _name):Component(_id, _name, SYS_SAGE_COMPONENT_QUANTUM_BACKEND){} + +QuantumBackend::QuantumBackend(Component * _parent, int _id, string _name):Component(_parent, _id, _name, SYS_SAGE_COMPONENT_QUANTUM_BACKEND){} + +void QuantumBackend::SetNumberofQubits(int _num_qubits) { num_qubits = _num_qubits; } + +int QuantumBackend::GetNumberofQubits() const { return num_qubits; } + +void QuantumBackend::addGate(QuantumGate *_gate) +{ + gate_types.push_back(_gate); +} + +std::vector QuantumBackend::GetGatesBySize(size_t _gate_size) const +{ + std::vector gates; + gates.reserve(gate_types.size()); + + for (QuantumGate * gate : gate_types) + { + if(_gate_size == gate->GetGateSize()) + gates.emplace_back(gate); + } + + return gates; +} + +std::vector QuantumBackend::GetGatesByType(size_t _gate_type) const +{ + std::vector gates; + gates.reserve(gate_types.size()); + + for (QuantumGate * gate : gate_types) + { + if(_gate_type == gate->GetType()) + gates.emplace_back(gate); + } + + return gates; +} + +std::vector QuantumBackend::GetAllGateTypes() const +{ + return gate_types; +} + +int QuantumBackend::GetNumberofGates() const { return gate_types.size(); } + +std::vector QuantumBackend::GetAllQubits() +{ + auto all_children = GetAllChildrenByType(SYS_SAGE_COMPONENT_QUBIT); + std::vector qubits; + qubits.reserve(all_children.size()); + + for (size_t i = 0; i < all_children.size(); ++i) + { + Qubit* q = dynamic_cast(all_children[i]); + qubits.push_back(q); + } + + return qubits; +} + +std::set > QuantumBackend::GetAllCouplingMaps() +{ + std::set> result; + for(auto i = 0; i < num_qubits; ++i) + { + Qubit* q = dynamic_cast(GetChild(i)); + auto coupling_map = q->GetCouplingMapping(); + for (size_t j = 0; j < coupling_map.size(); ++j) + { + result.emplace(i, coupling_map[j]); + } + } + + return result; +} + +void QuantumBackend::SetQDMIDevice(QDMI_Device dev) +{ + device = dev; +} + +QDMI_Device QuantumBackend::GetQDMIDevice(){ return device; } + +Qubit::Qubit(int _id, string _name):Component(_id, _name, SYS_SAGE_COMPONENT_QUBIT){} + +Qubit::Qubit(Component * parent, int _id, string _name):Component(parent, _id, _name, SYS_SAGE_COMPONENT_QUBIT){} + +void Qubit::SetCouplingMapping( const std::vector &coupling_mapping, const int &size_coupling_mapping) +{ + _coupling_mapping = coupling_mapping; + _size_coupling_mapping = size_coupling_mapping; +} + +const std::vector & Qubit::GetCouplingMapping() const +{ + return _coupling_mapping; +} + +void Qubit::SetProperties(double t1, double t2, double readout_error, double readout_length) +{ + _t1 = t1; + _t2 = t2; + _readout_error = readout_error; + _readout_length = readout_length; + +} + +const double Qubit::GetT1() const { return _t1; } +const double Qubit::GetT2() const { return _t2; } +const double Qubit::GetReadoutError() const { return _readout_error; } +const double Qubit::GetReadoutLength() const { return _readout_length; } diff --git a/src/Component.hpp b/src/Component.hpp index 8ced774..b514853 100644 --- a/src/Component.hpp +++ b/src/Component.hpp @@ -9,6 +9,8 @@ #include "defines.hpp" #include "DataPath.hpp" #include +#include +// #include #define SYS_SAGE_COMPONENT_NONE 1 /**< class Component (do not use normally)*/ @@ -23,6 +25,13 @@ #define SYS_SAGE_COMPONENT_NODE 512 /**< class Node */ #define SYS_SAGE_COMPONENT_TOPOLOGY 1024 /**< class Topology */ +/* To-do: Add defines for different quantum backends +* For e.g.: SYS_SAGE_COMPONENT_NEUTRAL_ATOMS, SYS_SAGE_COMPONENT_SUPERCONDUCTING, etc. + +*/ +#define SYS_SAGE_COMPONENT_QUANTUM_BACKEND 2048 /**< class QuantumBackend */ +#define SYS_SAGE_COMPONENT_QUBIT 4096 /**< class Qubit */ + #define SYS_SAGE_SUBDIVISION_TYPE_NONE 1 /**< Generic Subdivision type. */ #define SYS_SAGE_SUBDIVISION_TYPE_GPU_SM 2 /**< Subdivision type for GPU SMs */ @@ -31,10 +40,10 @@ #define SYS_SAGE_CHIP_TYPE_CPU_SOCKET 4 /**< Chip type used for one CPU socket. */ #define SYS_SAGE_CHIP_TYPE_GPU 8 /**< Chip type used for a GPU.*/ - using namespace std; +class Relation; class DataPath; - +class QuantumGate; /** Generic class Component - all components inherit from this class, i.e. this class defines attributes and methods common to all components. \n Therefore, these can be used universally among all components. Usually, a Component instance would be an instance of one of the child classes, but a generic component (instance of class Component) is also possible. @@ -388,7 +397,7 @@ class Component { /** Retrieves a DataPath * from the list of this component's data paths with matching type and orientation. \n The first match is returned -- first SYS_SAGE_DATAPATH_OUTGOING are searched, then SYS_SAGE_DATAPATH_INCOMING. - @param dp_type - DataPath type (dp_type) to search for + @param type - DataPath type (type) to search for @param orientation - orientation of the DataPath (SYS_SAGE_DATAPATH_OUTGOING or SYS_SAGE_DATAPATH_INCOMING or a logical or of these) @return DataPath pointer to the found data path; NULL if nothing found. */ @@ -396,7 +405,7 @@ class Component { /** Retrieves all DataPath * from the list of this component's data paths with matching type and orientation. Results are returned in vector* outDpArr, where first the matching data paths in dp_outgoing are pushed back, then the ones in dp_incoming. - @param dp_type - DataPath type (dp_type) to search for. + @param type - DataPath type (type) to search for. @param orientation - orientation of the DataPath (SYS_SAGE_DATAPATH_OUTGOING or SYS_SAGE_DATAPATH_INCOMING or a logical or of these) @param outDpArr - output parameter (vector with results) \n An input is pointer to a std::vector, in which the data paths will be pushed. It must be allocated before the call (but does not have to be empty). @@ -1175,4 +1184,236 @@ class Thread : public Component { private: }; +class Qubit : public Component { +public: + /** + Qubit constructor (no automatic insertion in the Component Tree). Sets: + @param _id = id, default 0 + @param _name = name, default "Qubit" + @param componentType=>SYS_SAGE_COMPONENT_QUBIT + */ + Qubit(int _id = 0, string _name = "Qubit"); + /** + Qubit constructor with insertion into the Component Tree as the parent 's child (as long as parent is an existing Component). Sets: + @param parent = the parent + @param _id = id, default 0 + @param _name = name, default "Qubit0" + @param componentType=>SYS_SAGE_COMPONENT_QUBIT + */ + Qubit(Component * parent, int _id = 0, string _name = "Qubit"); + + /** + * @brief Sets the coupling mapping for the qubit. + * + * @param coupling_mapping A vector of integers representing the coupling mapping. + * @param size_coupling_mapping The size of the coupling mapping. + */ + void SetCouplingMapping( const std::vector &coupling_mapping, const int &size_coupling_mapping); + + /** + * @brief Sets the properties of the qubit. + * + * @param t1 The T1 relaxation time. + * @param t2 The T2 dephasing time. + * @param readout_error The readout error rate. + * @param readout_length The readout length. + */ + void SetProperties(double t1, double t2, double readout_error, double readout_length); + + /** + * @brief Gets the coupling mapping of the qubit. + * + * @return A constant reference to a vector of integers representing the coupling mapping. + */ + const std::vector &GetCouplingMapping() const; + + /** + * @brief Gets the T1 relaxation time of the qubit. + * + * @return The T1 relaxation time. + */ + const double GetT1() const; + /** + * @brief Gets the T2 dephasing time of the qubit. + * + * @return The T2 dephasing time. + */ + const double GetT2() const; + + /** + * @brief Gets the readout error rate of the qubit. + * + * @return The readout error rate. + */ + const double GetReadoutError() const; + + /** + * @brief Gets the readout length of the qubit. + * + * @return The readout length. + */ + const double GetReadoutLength() const; + + /** + * @brief Gets the frequency of the qubit. + * + * @return The frequency of the qubit. + */ + const double GetFrequency() const; + + /** + * @brief Refreshes the properties of the qubit. + */ + void RefreshProperties(); + + ~Qubit() override = default; + +private: + std::vector _coupling_mapping; + int _size_coupling_mapping; + double fidelity; + double _t1; + double _t2; + double _readout_error; + double _readout_length; + double _fequency; + std::string _calibration_time; +}; + + +class QuantumBackend : public Component { +public: + /** + QuantumBackend constructor (no automatic insertion in the Component Tree). Sets: + @param _id = id, default 0 + @param _name = name, default "QuantumBackend" + @param componentType=>SYS_SAGE_COMPONENT_QUANTUM_BACKEND + */ + QuantumBackend(int _id = 0, string _name = "QuantumBackend"); + /** + QuantumBackend constructor with insertion into the Component Tree as the parent 's child (as long as parent is an existing Component). Sets: + @param parent = the parent + @param _id = id, default 0 + @param _name = name, default "QuantumBackend" + @param componentType=>SYS_SAGE_COMPONENT_QUANTUM_BACKEND + */ + QuantumBackend(Component * parent, int _id = 0, string _name = "QuantumBackend"); + + /** + * @brief Sets the number of qubits in the quantum backend. + * + * @param _num_qubits The number of qubits to set. + */ + void SetNumberofQubits(int _num_qubits); + + /** + * @brief Sets the QDMI device for the quantum backend. + * + * @param dev The QDMI device to set. + */ + void SetQDMIDevice(QDMI_Device dev); + + /** + * @brief Gets the QDMI device of the quantum backend. + * + * @return The QDMI device. + */ + QDMI_Device GetQDMIDevice(); + + /** + * @brief Gets the number of qubits in the quantum backend. + * + * @return The number of qubits. + */ + int GetNumberofQubits () const; + + /** + * @brief Adds a quantum gate to the quantum backend. + * + * @param gate The quantum gate to add. + */ + void addGate(QuantumGate *gate); + + /** + * @brief Gets the quantum gates by their size. + * + * @param _gate_size The size of the gates to retrieve. + * @return A vector of quantum gates with the specified size. + */ + std::vector GetGatesBySize(size_t _gate_size) const; + + /** + * @brief Gets the quantum gates by their type. + * + * @param _gate_type The type of the gates to retrieve. + * @return A vector of quantum gates with the specified type. + */ + std::vector GetGatesByType(size_t _gate_type) const; + + /** + * @brief Gets all types of quantum gates in the quantum backend. + * + * @return A vector of all quantum gate types. + */ + std::vector GetAllGateTypes() const; + + /** + * @brief Gets the number of quantum gates in the quantum backend. + * + * @return The number of quantum gates. + */ + int GetNumberofGates() const; + + /** + * @brief Gets all qubits in the quantum backend. + * + * @return A vector of pointers to all qubits. + */ + std::vector GetAllQubits(); + + /** + * @brief Gets all coupling maps in the quantum backend. + * + * @return A set of pairs representing the coupling maps. + */ + std::set > GetAllCouplingMaps(); + + /** + * @brief Refreshes the topology of the quantum backend. + * + * @param qubit_indices The indices of the qubits that need to be refreshed. + */ + void RefreshTopology(std::set qubit_indices); // qubit_indices: indices of the qubits that need to be refreshed + + ~QuantumBackend() override = default; + +private: + int num_qubits; + int num_gates; + QDMI_Device device; // For refreshing the topology + std::vector gate_types; +}; + +// TO-DO: Choose a better name for NA and TI systems +class AtomSite : public QuantumBackend{ +public: + struct SiteProperties { + + int nRows; + int nColumns; + int nAods; + int nAodIntermediateLevels; + int nAodCoordinates; + double interQubitDistance; + double interactionRadius; + double blockingFactor; + } properties; + + std::map shuttlingTimes; + std::map shuttlingAverageFidelities; + +}; + #endif + + diff --git a/src/DataPath.cpp b/src/DataPath.cpp index 90da610..09ca0cd 100644 --- a/src/DataPath.cpp +++ b/src/DataPath.cpp @@ -3,6 +3,13 @@ #include #include +void Relation::SetType(int _type) {_type = type;} +int Relation::GetType(){ return type;} +void Relation::SetId(int _id) {id = _id;} +int Relation::GetId(){ return id;} +void Relation::SetName(std::string _name) { name = _name;} +std::string Relation::GetName() {return name;} + DataPath* NewDataPath(Component* _source, Component* _target, int _oriented, int _type){ DataPath *dp = new DataPath(_source, _target, _oriented, _type, -1, -1); return dp; @@ -80,7 +87,7 @@ void DataPath::UpdateTarget(Component * _new_target) DataPath::DataPath(Component* _source, Component* _target, int _oriented, int _type): DataPath(_source, _target, _oriented, _type, -1, -1) {} DataPath::DataPath(Component* _source, Component* _target, int _oriented, double _bw, double _latency): DataPath(_source, _target, _oriented, SYS_SAGE_DATAPATH_TYPE_NONE, _bw, _latency) {} -DataPath::DataPath(Component* _source, Component* _target, int _oriented, int _type, double _bw, double _latency): source(_source), target(_target), oriented(_oriented), dp_type(_type), bw(_bw), latency(_latency) +DataPath::DataPath(Component* _source, Component* _target, int _oriented, int _type, double _bw, double _latency): source(_source), target(_target), oriented(_oriented), type(_type), bw(_bw), latency(_latency) { if(_oriented == SYS_SAGE_DATAPATH_BIDIRECTIONAL) { @@ -139,3 +146,97 @@ void DataPath::Print() } cout << endl; } + +void DataPath::DeleteRelation() +{ + DeleteDataPath(); +} + +QuantumGate::QuantumGate() +{ + gate_size = 1; + type = SYS_SAGE_1Q_QUANTUM_GATE; +} + +QuantumGate::QuantumGate(size_t _gate_size) : gate_size(_gate_size){} + +QuantumGate::QuantumGate(size_t _gate_size, std::string _name, double _fidelity, std::string _unitary) +: gate_size(_gate_size), fidelity(_fidelity), unitary(_unitary){ name =_name ;} + +QuantumGate::QuantumGate(size_t _gate_size, const std::vector & _qubits) +: gate_size(_gate_size), qubits(_qubits) {} + +QuantumGate::QuantumGate(size_t _gate_size, const std::vector & _qubits, std::string _name, double _fidelity, std::string _unitary) +: gate_size(_gate_size), qubits(_qubits), fidelity(_fidelity), unitary(_unitary) { name =_name ;} + +void QuantumGate::SetGateProperties(std::string _name, double _fidelity, std::string _unitary) +{ + name = _name; + fidelity = _fidelity; + unitary = _unitary; + SetType(); +} + + +void QuantumGate::SetType() +{ + if(gate_size == 1) + { + if(name == "id") type = SYS_SAGE_QUANTUMGATE_TYPE_ID; + else if(name == "rz") type = SYS_SAGE_QUANTUMGATE_TYPE_RZ; + else if(name == "sx") type = SYS_SAGE_QUANTUMGATE_TYPE_SX; + else if(name == "x") type = SYS_SAGE_QUANTUMGATE_TYPE_X; + else type = SYS_SAGE_QUANTUMGATE_TYPE_UNKNOWN; + } + + else if(gate_size == 2) + { + if(name == "cx") type = SYS_SAGE_QUANTUMGATE_TYPE_CNOT; + else type = SYS_SAGE_QUANTUMGATE_TYPE_UNKNOWN; + } + + else if(gate_size > 2) + { + if(name == "toffoli") type = SYS_SAGE_QUANTUMGATE_TYPE_TOFFOLI; + else type = SYS_SAGE_QUANTUMGATE_TYPE_UNKNOWN; + } + + else + { + type = SYS_SAGE_QUANTUMGATE_TYPE_UNKNOWN; + } + +} + +int QuantumGate::GetType() +{ + return type; +} + +double QuantumGate::GetFidelity() const +{ + return fidelity; +} + +size_t QuantumGate::GetGateSize() const +{ + return gate_size; +} + +std::string QuantumGate::GetUnitary() const +{ + return unitary; +} + +std::string QuantumGate::GetName() +{ + return name; +} + +void QuantumGate::Print() +{ +} + +void QuantumGate::DeleteRelation() +{ +} diff --git a/src/DataPath.hpp b/src/DataPath.hpp index 5453380..a2850dd 100644 --- a/src/DataPath.hpp +++ b/src/DataPath.hpp @@ -1,7 +1,9 @@ -#ifndef DATAPATH -#define DATAPATH +#ifndef RELATION_HPP +#define RELATION_HPP #include +#include +#include #include "defines.hpp" #include "Component.hpp" @@ -9,13 +11,13 @@ //Component pointing to a DataPath #define SYS_SAGE_DATAPATH_NONE 1 /**< Reserved for development purposes. */ #define SYS_SAGE_DATAPATH_OUTGOING 2 /**< This Component is the source DataPath. */ -#define SYS_SAGE_DATAPATH_INCOMING 4 /**< This Component is the taerget DataPath. */ +#define SYS_SAGE_DATAPATH_INCOMING 4 /**< This Component is the target DataPath. */ //int oriented #define SYS_SAGE_DATAPATH_BIDIRECTIONAL 8 /**< DataPath has no direction. */ -#define SYS_SAGE_DATAPATH_ORIENTED 16 /**< DataPath is directec from the source to the target. */ +#define SYS_SAGE_DATAPATH_ORIENTED 16 /**< DataPath is directed from the source to the target. */ -//dp_type +//datapath type #define SYS_SAGE_DATAPATH_TYPE_NONE 32 /**< Generic type of DataPath */ #define SYS_SAGE_DATAPATH_TYPE_LOGICAL 64 /**< DataPath describes a logical connection/relation of two Components. */ #define SYS_SAGE_DATAPATH_TYPE_PHYSICAL 128 /**< DataPath describes a physical/hardware connection/relation of two Components. */ @@ -24,10 +26,124 @@ #define SYS_SAGE_DATAPATH_TYPE_DATATRANSFER 1024 /**< DataPath type describing data transfer attributes. */ #define SYS_SAGE_DATAPATH_TYPE_C2C 2048 /**< DataPath type describing cache-to-cache latencies (cccbench data source). */ -using namespace std; +#define SYS_SAGE_1Q_QUANTUM_GATE 1 /**< Quantum Gate of size 1-Qubit. */ +#define SYS_SAGE_2Q_QUANTUM_GATE 2 /**< Quantum Gate of size 2-Qubits. */ +#define SYS_SAGE_MQ_QUANTUM_GATE 4 /**< Quantum Gate of size M-Qubits (where M >2). */ +#define SYS_SAGE_NO_TYPE_QUANTUM_GATE 0 /**< Quantum Gate of size 0 or invalid size. */ + + +// QuantumGate type +#define SYS_SAGE_QUANTUMGATE_TYPE_ID 32 /**< Identity Gate */ +#define SYS_SAGE_QUANTUMGATE_TYPE_RZ 64 /**< RZ Gate */ +#define SYS_SAGE_QUANTUMGATE_TYPE_CNOT 128 /**< CNOT Gate */ +#define SYS_SAGE_QUANTUMGATE_TYPE_SX 256 /**< SX Gate */ +#define SYS_SAGE_QUANTUMGATE_TYPE_X 512 /**< X Gate */ +#define SYS_SAGE_QUANTUMGATE_TYPE_TOFFOLI 1024 /**< Toffoli Gate */ +#define SYS_SAGE_QUANTUMGATE_TYPE_UNKNOWN 2048 /**< Unknown Gate */ class Component; -class DataPath; +class Qubit; + +/** + * @class Relation + * @brief Represents a generic relationship or connectivity between two components. + * + * This class defines a generic relationship with methods to set and get + * the type, id, and name of the relationship. It also provides pure virtual + * functions for printing and deleting the relationship, making it an abstract class. + */ +class Relation { +public: + /** + * @brief Sets the type of the relationship. + * @param _type The type of the relationship to set. + */ + void SetType(int _type); + + /** + * @brief Gets the type of the relationship. + * @return The current type of the relationship. + */ + int GetType(); + + /** + * @brief Sets the id of the relationship. + * @param _id The id of the relationship to set. + */ + void SetId(int _id); + + /** + * @brief Gets the id of the relationship. + * @return The current id of the relationship. + */ + int GetId(); + + /** + * @brief Sets the name of the relationship. + * @param _name The name of the relationship to set. + */ + void SetName(std::string _name); + + /** + * @brief Gets the name of the relationship. + * @return The current name of the relationship. + */ + std::string GetName(); + + /** + * @brief Destructor for the Relation class. + * + * This is a virtual destructor to ensure proper cleanup of derived classes. + */ + virtual ~Relation() = default; + + /** + * @brief Pure virtual function to print the details of the relationship. + * + * Derived classes must implement this function to provide specific + * printing behavior. + */ + virtual void Print() = 0; + + /** + * @brief Pure virtual function to delete the relationship. + * + * Derived classes must implement this function to provide specific + * deletion behavior. + */ + virtual void DeleteRelation() = 0; + + /** + * @brief The id of the relationship. + * + * This member variable stores the unique identifier for the relationship. + */ + int id; + + /** + * @brief The type of the relationship. + * + * This member variable stores the type or category of the relationship. + */ + int type; + + /** + * @brief The name of the relationship. + * + * This member variable stores the name or description of the relationship. + */ + std::string name; + /** + * @brief A vector of components associated with the relationship. + * + * This member variable holds pointers to components that are part of + * the relationship. + */ + std::vector components; + +}; + +class DataPath; /** @private Obsolete; use DataPath() constructors directly instead @@ -55,7 +171,8 @@ Class DataPath represents Data Paths in the topology -- Data Paths represent an \n Data Paths create a Data-Path graph, which is a structure orthogonal to the Component Tree. \n Each Component contains a reference to all Data Paths going to or from this components (as well as parents and children in the Component Tree). Using these references, it is possible to navigate between the Components and to view the data stores in the Components or the Data Paths. */ -class DataPath { + +class DataPath : public Relation { public: /** @@ -134,8 +251,10 @@ class DataPath { void UpdateTarget(Component * _new_target); /** + * @private + Obsolete;use GetType() instead. @returns Type of the Data Path. - @see dp_type + @see type */ int GetDataPathType(); /** @@ -157,7 +276,8 @@ class DataPath { @see dp_outgoing */ void DeleteDataPath(); - + + void DeleteRelation() override; /** * A map for storing arbitrary pieces of information or data. * - The `key` denotes the name of the attribute. @@ -244,4 +364,185 @@ class DataPath { }; -#endif +/** + * @class QuantumGate + * @brief Represents a quantum gate in a quantum circuit. + * + * This class extends the Relation class to model quantum gates. + * It includes various properties specific to quantum gates, such as gate size, fidelity, and unitary matrix. + * The class also handles the coupling map and additional properties related to quantum gate operations. + */ +class QuantumGate : public Relation { + +public: + /** + * @brief Default constructor for QuantumGate. + * + * Initializes a quantum gate with default properties. + */ + QuantumGate(); + + /** + * @brief Constructor that initializes a quantum gate with a specified size. + * @param _gate_size The number of qubits this gate operates on. + */ + QuantumGate(size_t _gate_size); + + /** + * @brief Constructor that initializes a quantum gate with specific properties. + * @param _gate_size The number of qubits this gate operates on. + * @param _name The name of the quantum gate. + * @param _fidelity The fidelity of the quantum gate. + * @param _unitary The unitary matrix representing the quantum gate operation. + */ + QuantumGate(size_t _gate_size, std::string _name, double _fidelity, std::string _unitary); + + /** + * @brief Constructor that initializes a quantum gate with a list of qubits. + * @param _gate_size The number of qubits this gate operates on. + * @param _qubits A vector of pointers to Qubit objects that the gate operates on. + */ + QuantumGate(size_t _gate_size, const std::vector & _qubits); + + /** + * @brief Constructor that initializes a quantum gate with detailed properties and qubits. + * @param _gate_size The number of qubits this gate operates on. + * @param _qubits A vector of pointers to Qubit objects that the gate operates on. + * @param _name The name of the quantum gate. + * @param _fidelity The fidelity of the quantum gate. + * @param _unitary The unitary matrix representing the quantum gate operation. + */ + QuantumGate(size_t _gate_size, const std::vector & _qubits, std::string _name, double _fidelity, std::string _unitary); + + /** + * @brief Sets the properties of the quantum gate. + * @param _name The name of the quantum gate. + * @param _fidelity The fidelity of the quantum gate. + * @param _unitary The unitary matrix representing the quantum gate operation. + */ + void SetGateProperties(std::string _name, double _fidelity, std::string _unitary); + + /** + * @brief Sets the coupling map for the quantum gate. + * @param _coupling_mapping A vector of vectors of pointers to Qubit objects representing the coupling map. + */ + void SetGateCouplingMap(std::vector> _coupling_mapping); + + /** + * @brief Sets additional properties for the quantum gate. + * + * This function allows setting properties that are not part of the core quantum gate attributes. + */ + void SetAdditionalProperties(); + + /** + * @brief Sets the type of the quantum gate. + * + * Sets the specific type for quantum gates. + */ + void SetType(); + + /** + * @brief Gets the type of the quantum gate. + * @return The type identifier for the quantum gate. + */ + int GetType(); + + /** + * @brief Gets the fidelity of the quantum gate. + * @return The fidelity of the quantum gate. + */ + double GetFidelity() const; + + /** + * @brief Gets the size of the quantum gate. + * @return The number of qubits this gate operates on. + */ + size_t GetGateSize() const; + + /** + * @brief Sets the id of the quantum gate. + * @param _id The id to assign to the quantum gate. + */ + void SetId(int _id); + + /** + * @brief Gets the id of the quantum gate. + * @return The id of the quantum gate. + */ + int GetId(); + + /** + * @brief Gets the unitary matrix of the quantum gate. + * @return A string representing the unitary matrix of the quantum gate. + */ + std::string GetUnitary() const; + + /** + * @brief Gets the name of the quantum gate. + * @return The name of the quantum gate. + */ + std::string GetName(); + + /** + * @brief Prints the details of the quantum gate. + * + * This method overrides the Print function in the Relation class to provide specific printing behavior for quantum gates. + */ + void Print() override; + + /** + * @brief Deletes the quantum gate relation. + * + * This method overrides the DeleteRelation function in the Relation class to handle specific deletion behavior for quantum gates. + */ + void DeleteRelation() override; + +private: + + /** + * @brief The size of the quantum gate, representing the number of qubits it operates on. + */ + size_t gate_size; + + /** + * @brief The length of the quantum gate operation in terms of time or depth. + */ + int gate_length; + + /** + * @brief The unitary matrix representing the quantum gate's operation. + * + * This string stores a serialized or symbolic representation of the unitary matrix. + */ + std::string unitary; + + /** + * @brief The fidelity of the quantum gate, indicating its accuracy or performance. + */ + double fidelity; + + /** + * @brief The coupling map for the quantum gate. + * + * This 2D vector of qubit pointers represents the coupling map, defining how qubits interact within the gate. + */ + std::vector> coupling_mapping; + + /** + * @brief List of the qubits involved in a quantum gate. + * + * This vector of qubit pointers stores the list of the qubits involved in the gate. + */ + std::vector qubits; + + /** + * @brief Additional properties of the quantum gate. + * + * This map allows storing additional key-value pairs representing various other properties related to the quantum gate. + */ + std::map additional_properties; +}; + + +#endif // RELATION_HPP diff --git a/src/parsers/qdmi-parser.cpp b/src/parsers/qdmi-parser.cpp new file mode 100644 index 0000000..81427aa --- /dev/null +++ b/src/parsers/qdmi-parser.cpp @@ -0,0 +1,276 @@ +/** + * @file qdmi-parser.hpp + * @brief sys-sage's interface to QDMI. + */ + +#include "qdmi-parser.hpp" + +QInfo QdmiParser::info; +QDMI_Session QdmiParser::session; + +extern "C" QdmiParser::QdmiParser() +{ + initiateSession(); +} + +extern "C" int QdmiParser::initiateSession() +{ + int err = 0; + QdmiParser::info = NULL; + QdmiParser::session = NULL; + + err = QInfo_create(&QdmiParser::info); + CHECK_ERR(err, "QInfo_create"); + + err = QDMI_session_init(QdmiParser::info, &QdmiParser::session); + CHECK_ERR(err, "QDMI_session_init"); + if (err != QDMI_SUCCESS) + { + std::cout << " [sys-sage]...............Unable to initiate " + << "QDMI session\n"; + exit(0); + } + std::cout << " [sys-sage]...............Initiated " + << "QDMI session\n"; + return 0; + +} + +extern "C" std::vector QdmiParser::get_available_backends() +{ + + int count; + QDMI_core_device_count(&QdmiParser::session, &count); + + if(count == 0){ + std::cout << " [sys-sage]...............QDMI_core_device_count from QDMI returned 0." << std::endl; + return {}; + } + + else { + std::cout << " [sys-sage]...............QDMI_core_device_count returned " << count << ".\n"; + } + + std::vector registered_devices; + char **available_devices = get_qdmi_library_list_names(); // --> + if (available_devices == NULL) + { + std::cout << " [sys-sage]...............Failed to get " + << "qdmi_library_list from QDMI" << std::endl; + + return {}; + } + + for(int i = 0; i < count; i++){ + QDMI_Device device; + QDMI_core_open_device(&QdmiParser::session, i , &QdmiParser::info, &device); + + registered_devices.emplace_back(device); + } + + return registered_devices; +} + +extern "C" int QdmiParser::get_num_qubits(QDMI_Device dev) +{ + int err, num_qubits = 0; + + err = QDMI_query_qubits_num(dev, &num_qubits); + + if (err != QDMI_SUCCESS || num_qubits == 0) + { + std::cout << " [sys-sage]...............Could not obtain number of " + << "available qubits via QDMI\n"; + return -1; + } + return num_qubits; + +} + +extern "C" void QdmiParser::getCouplingMapping(QDMI_Device dev, QDMI_Qubit qubit, std::vector &coupling_mapping, int &coupling_map_size) +{ + + if (qubit->size_coupling_mapping == 0) + { + std::cout << " [sys-sage]...............No coupling mapping for qubit\n"; + return; + } + + coupling_map_size = qubit->size_coupling_mapping; + coupling_mapping.resize(coupling_map_size); + + std::copy(qubit->coupling_mapping, qubit->coupling_mapping + coupling_map_size, coupling_mapping.begin()); +} + +extern "C" void QdmiParser::getQubitProperties(QDMI_Device dev, QDMI_Qubit qubit) +{ + int scope; + // Declare prop as a vector + std::vector prop{QDMI_T1_TIME, QDMI_T2_TIME, QDMI_READOUT_ERROR, QDMI_READOUT_LENGTH}; + std::array properties{"T1", "T2", "readout_error", "readout_length"}; + double value; + for (size_t i = 0; i < 4; ++i) + { + // QDMI_Qubit_property prop_index; + QDMI_Qubit_property prop_index = new (QDMI_Qubit_property_impl_t); + prop_index->name = prop[i]; + int err = QDMI_query_qubit_property_exists(dev, qubit, prop_index, &scope); + if(err) + { + std::cout << " [sys-sage]...............Queried property doesn't exist: " << i <<"\n"; + continue; + } + + if(prop_index->type == QDMI_DOUBLE){ + err = QDMI_query_qubit_property_d(dev, qubit, prop_index, &value); + if(err) + { + std::cout << " [sys-sage]...............Unable to query property: " << i <<"\n"; + continue; + } + + } + delete prop_index; + + } + +} + +extern "C" void QdmiParser::setQubits(QuantumBackend *backend, QDMI_Device dev) +{ + QDMI_Qubit qubits; + int err, num_qubits = 0; + + err = QDMI_query_all_qubits(dev, &qubits); + + if (err != QDMI_SUCCESS || qubits == NULL) + { + std::cout << " [sys-sage]...............Could not obtain available " + << "qubits via QDMI\n"; + return; + } + + num_qubits = backend->GetNumberofQubits(); + + for (int i = 0; i < num_qubits; i++) + { + Qubit* q = new Qubit(backend, i); + + // Set coupling map + int coupling_map_size; + std::vector coupling_mapping; + getCouplingMapping(dev, &qubits[i], coupling_mapping, coupling_map_size); + q->SetCouplingMapping(coupling_mapping, coupling_map_size); + + // Set all the qubit properties + getQubitProperties(dev, &qubits[i]); + q->SetProperties(qubits[i].t1, qubits[i].t2, qubits[i].readout_error, qubits[i].readout_length); + } + + free(qubits); + return; +} + +extern "C" void QdmiParser::setGateSets(QuantumBackend *backend, QDMI_Device dev) +{ + QDMI_Gate gates; + int err, num_gates; + + err = QDMI_query_all_gates(dev, &gates); + + if (err != QDMI_SUCCESS || gates == NULL) + { + std::cout << " [sys-sage]...............Could not obtain available " + << "gates via QDMI\n"; + return; + } + + err = QDMI_query_gateset_num(dev, &num_gates); + + if (err != QDMI_SUCCESS || num_gates == 0) + { + std::cout << " [sys-sage]...............Could not obtain number of " + << "available gates via QDMI\n"; + return; + } + else + { + std::cout << " [sys-sage]...............Found " + << num_gates << " supported gates.\n"; + } + + for (int i = 0; i < num_gates; i++) + { + + std::string name = gates[i].name; + double fidelity = gates[i].fidelity; + std::string unitary = gates[i].unitary; + size_t gate_size = gates[i].gate_size; + + // Add a constructor + QuantumGate *qgate = new QuantumGate(gate_size); + qgate->SetGateProperties(name, fidelity, unitary); + + backend->addGate(qgate); + } + + + free(gates); + + return; +} + +extern "C" void QdmiParser::createAllQcTopo(Topology *topo) +{ + auto quantum_backends = get_available_backends(); + + int total_quantum_backends = quantum_backends.size(); + + for (auto i = 0; i < total_quantum_backends; ++i) + { + QuantumBackend* qc = new QuantumBackend(topo, i); + createQcTopo(qc, quantum_backends[i]); + } + +} + +extern "C" Topology QdmiParser::createAllQcTopo() +{ + + Topology qc_topo = Topology(); + createAllQcTopo(&qc_topo); + + return qc_topo; +} + +extern "C" void QdmiParser::createQcTopo(QuantumBackend *backend, QDMI_Device dev) +{ + backend->SetNumberofQubits(get_num_qubits(dev)); + setQubits(backend, dev); + setGateSets(backend, dev); +} + +extern "C" QuantumBackend QdmiParser::createQcTopo(QDMI_Device dev, int device_index, std::string device_name) +{ + QuantumBackend qc = QuantumBackend(device_index, device_name); + createQcTopo(&qc, dev); + + return qc; +} + +void QuantumBackend::RefreshTopology(std::set qubit_indices) +{ + + for (auto q : qubit_indices) { + auto qubit = dynamic_cast(GetChild(q)); + qubit->RefreshProperties(); + } +} + +void Qubit::RefreshProperties() +{ + + QuantumBackend *qc = dynamic_cast (this->GetParent()); + QdmiParser::refreshQubitProperties(qc->GetQDMIDevice(), this); + +} \ No newline at end of file diff --git a/src/parsers/qdmi-parser.hpp b/src/parsers/qdmi-parser.hpp new file mode 100644 index 0000000..b85e273 --- /dev/null +++ b/src/parsers/qdmi-parser.hpp @@ -0,0 +1,135 @@ +/** +* @file qdmi-parser.hpp +* @brief sys-sage's interface to QDMI. +*/ + +#ifndef QDMIParser_HPP +#define QDMIParser_HPP + +#include +#include +#include +#include +#include "Topology.hpp" +#include + +#define CHECK_ERR(a,b) { if (a!=QDMI_SUCCESS) { printf("\n[Error]: %i at %s",a,b); return 1; }} + +extern "C" +{ + + class QdmiParser + { + public: + QdmiParser(); + + /** + * Returns all the available backends registered with QDMI. + * @return A vector of all the backends with their names and "QDMI_Device" handles + */ + std::vector get_available_backends(); + + int get_num_qubits(QDMI_Device dev); + /** + * Checks which backends are available and creates a topology with an object of type "Topology" as their parent. + * @param topo - Object of type "Topology", which will be the parent Component of all the quntum backends. + */ + void createAllQcTopo(Topology *topo); + + /** + * Checks which backends are available and creates a topology with an object of type "Topology" as their parent. + * @returns An object of type "Topology", which will be the parent Component of all the quntum backends. + * @see createAllQcTopo(Topology *topo) + */ + Topology createAllQcTopo(); + + /** + * Creates a topology of a single quantum backend corresponding to the provided "QDMI_Device". + * @param backend - Object of type "QuantumBackend", storing the topology of a quantum backend. + * @param dev - A QDMI_Device for which the topology needs to be created. + * @see createQcTopo(Topology *topo) + */ + void createQcTopo(QuantumBackend *backend, QDMI_Device dev); + + /** + * Creates a topology of a single quantum backend corresponding to the provided "QDMI_Device". + * @param dev - A QDMI_Device for which the topology needs to be created. + * @param device_index - Index of the device. + * @param device_name - Name of the device. + * @returns Object of type "QuantumBackend", storing the topology of a quantum backend. + * @see createQcTopo(QuantumBackend *backend, QDMI_Device dev) + */ + QuantumBackend createQcTopo(QDMI_Device dev, int device_index = 0, std::string device_name=""); + + static void refreshQubitProperties(QDMI_Device dev, Qubit *q) + { + //Refresh Qubit properties + QDMI_Qubit qubits; + int err; + + err = QDMI_query_all_qubits(dev, &qubits); + + if (err != QDMI_SUCCESS || qubits == NULL) + { + std::cout << " [sys-sage]...............Could not obtain available " + << "qubits via QDMI\n"; + return; + } + int qubit_index = q->GetId(); + + // Refreshing Qubit coupling map + int coupling_map_size; + std::vector coupling_mapping; + coupling_map_size = (&qubits[qubit_index])->size_coupling_mapping; + coupling_mapping.resize(coupling_map_size); + std::copy(qubits[qubit_index].coupling_mapping, qubits[qubit_index].coupling_mapping + coupling_map_size, coupling_mapping.begin()); + q->SetCouplingMapping(coupling_mapping, coupling_map_size); + + + // Set all the qubit properties + int scope; + // Declare prop as a vector + std::vector prop{QDMI_T1_TIME, QDMI_T2_TIME, QDMI_READOUT_ERROR, QDMI_READOUT_LENGTH}; + std::array properties{"T1", "T2", "readout_error", "readout_length"}; + double value; + for (size_t i = 0; i < 4; ++i) + { + // QDMI_Qubit_property prop_index; + QDMI_Qubit_property prop_index = new (QDMI_Qubit_property_impl_t); + prop_index->name = prop[i]; + int err = QDMI_query_qubit_property_exists(dev, &qubits[qubit_index], prop_index, &scope); + if(err) + { + std::cout << " [sys-sage]...............Queried property doesn't exist: " << i <<"\n"; + continue; + } + err = QDMI_query_qubit_property_type(dev, &qubits[qubit_index], prop_index); + if(prop_index->type == QDMI_DOUBLE){ + err = QDMI_query_qubit_property_d(dev, &qubits[qubit_index], prop_index, &value); + if(err) + { + std::cout << " [sys-sage]...............Unable to query property: " << i <<"\n"; + continue; + } + //std::cout << " [sys-sage]...............Value of " << properties[i] << ": " << value << "\n"; + } + delete prop_index; + + } + + q->SetProperties(qubits[qubit_index].t1, qubits[qubit_index].t2, qubits[qubit_index].readout_error, qubits[qubit_index].readout_length); + } + private: + int initiateSession(); + static QInfo info; + static QDMI_Session session; + void getCouplingMapping(QDMI_Device dev, QDMI_Qubit qubit, std::vector &coupling_mapping, int &coupling_map_size); + void getQubitProperties(QDMI_Device dev, QDMI_Qubit qubit); + void setQubits(QuantumBackend *backend, QDMI_Device dev); + void setGateSets(QuantumBackend *backend, QDMI_Device dev); + + }; + +} + +#endif // QDMIParser_HPP \ No newline at end of file diff --git a/src/sys-sage.hpp b/src/sys-sage.hpp index cf7a1c2..9bc3bad 100644 --- a/src/sys-sage.hpp +++ b/src/sys-sage.hpp @@ -9,5 +9,5 @@ #include "parsers/caps-numa-benchmark.hpp" #include "parsers/mt4g.hpp" #include "parsers/cccbench.hpp" - +#include "parsers/qdmi-parser.hpp" #endif //SYS_SAGE diff --git a/test/resources/schema.xml b/test/resources/schema.xml index 7b99fc1..66d4f34 100644 --- a/test/resources/schema.xml +++ b/test/resources/schema.xml @@ -25,7 +25,7 @@ - + diff --git a/test/resources/sys-sage_custom_attributes.xml b/test/resources/sys-sage_custom_attributes.xml index 111b0e8..87dd9d1 100644 --- a/test/resources/sys-sage_custom_attributes.xml +++ b/test/resources/sys-sage_custom_attributes.xml @@ -269,41 +269,41 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/resources/sys-sage_sample_output.xml b/test/resources/sys-sage_sample_output.xml index 8c65ee4..e31e896 100644 --- a/test/resources/sys-sage_sample_output.xml +++ b/test/resources/sys-sage_sample_output.xml @@ -243,37 +243,37 @@ - - - - - - - - - - - - - - - - \ No newline at end of file