Skip to content

Commit

Permalink
Merge pull request #32 from Durganshu/qc-integration
Browse files Browse the repository at this point in the history
QC Integration in sys-sage
  • Loading branch information
stepanvanecek authored Nov 22, 2024
2 parents 87fb9fd + 4fdd666 commit 7ec8775
Show file tree
Hide file tree
Showing 16 changed files with 1,422 additions and 57 deletions.
13 changes: 13 additions & 0 deletions cmake/Findbackends.cmake
Original file line number Diff line number Diff line change
@@ -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")
9 changes: 9 additions & 0 deletions cmake/Findqinfo.cmake
Original file line number Diff line number Diff line change
@@ -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)
2 changes: 1 addition & 1 deletion docs/Concept.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
)
139 changes: 139 additions & 0 deletions examples/qdmi-test.cpp
Original file line number Diff line number Diff line change
@@ -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 <iostream>
#include <string.h>
#include <iomanip>
#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<QuantumBackend*>(qc_topo->GetChild(0));
int total_qubits = qc->CountAllSubcomponents();
for (int i = 0; i < total_qubits; i++)
{
Qubit* q = dynamic_cast<Qubit*>(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<Qubit*>(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<Qubit*>(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;
}
36 changes: 30 additions & 6 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -17,6 +18,7 @@ set(SOURCES
parsers/caps-numa-benchmark.cpp
parsers/mt4g.cpp
parsers/cccbench.cpp
parsers/qdmi-parser.cpp
)

set(HEADERS
Expand All @@ -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
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:inc>
$<INSTALL_INTERFACE:lib>
# 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 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:inc>
$<INSTALL_INTERFACE:lib>
)

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::
Expand All @@ -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})
120 changes: 120 additions & 0 deletions src/Component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 "";
}
Expand Down Expand Up @@ -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<QuantumGate*> QuantumBackend::GetGatesBySize(size_t _gate_size) const
{
std::vector<QuantumGate*> gates;
gates.reserve(gate_types.size());

for (QuantumGate * gate : gate_types)
{
if(_gate_size == gate->GetGateSize())
gates.emplace_back(gate);
}

return gates;
}

std::vector<QuantumGate*> QuantumBackend::GetGatesByType(size_t _gate_type) const
{
std::vector<QuantumGate*> gates;
gates.reserve(gate_types.size());

for (QuantumGate * gate : gate_types)
{
if(_gate_type == gate->GetType())
gates.emplace_back(gate);
}

return gates;
}

std::vector<QuantumGate*> QuantumBackend::GetAllGateTypes() const
{
return gate_types;
}

int QuantumBackend::GetNumberofGates() const { return gate_types.size(); }

std::vector<Qubit *> QuantumBackend::GetAllQubits()
{
auto all_children = GetAllChildrenByType(SYS_SAGE_COMPONENT_QUBIT);
std::vector<Qubit *> qubits;
qubits.reserve(all_children.size());

for (size_t i = 0; i < all_children.size(); ++i)
{
Qubit* q = dynamic_cast<Qubit*>(all_children[i]);
qubits.push_back(q);
}

return qubits;
}

std::set<std::pair<std::uint16_t, std::uint16_t> > QuantumBackend::GetAllCouplingMaps()
{
std::set<std::pair<std::uint16_t, std::uint16_t>> result;
for(auto i = 0; i < num_qubits; ++i)
{
Qubit* q = dynamic_cast<Qubit*>(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 <int> &coupling_mapping, const int &size_coupling_mapping)
{
_coupling_mapping = coupling_mapping;
_size_coupling_mapping = size_coupling_mapping;
}

const std::vector <int> & 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; }
Loading

0 comments on commit 7ec8775

Please sign in to comment.