Skip to content

Commit

Permalink
Add OpenQASM 3.0 parser
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-fink committed Oct 24, 2023
1 parent c7ff761 commit ef86fb2
Show file tree
Hide file tree
Showing 25 changed files with 4,883 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ if(BUILD_MQT_CORE_TESTS)
include(GoogleTest)
add_subdirectory(test)
endif()

# TODO: remove before merging
add_executable(main-test src/main.cpp)
target_link_libraries(main-test PUBLIC MQT::qfr)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The MQT Core library forms the backbone of the quantum software tools developed
- [MQT DDVis](https://github.com/cda-tum/mqt-ddvis): A Web-Application visualizing Decision Diagrams for Quantum Computing.
- [MQT SyReC](https://github.com/cda-tum/mqt-syrec): A Tool for Synthesis of Reversible Circuits/Quanutm Computing Oracles.

For a full list of tools and libraries, please visit the [MQT website](https://mqt.readthedocs.io/).
For a full list of tools and libraries, please run the [MQT website](https://mqt.readthedocs.io/).

<!-- SPHINX-START -->

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The MQT Core library forms the backbone of the quantum software tools developed
- [MQT DDVis](https://github.com/cda-tum/mqt-ddvis): A Web-Application visualizing Decision Diagrams for Quantum Computing.
- {doc}`MQT SyReC <syrec:index>`: A Tool for Synthesis of Reversible Circuits/Quantum Computing Oracles.

For a full list of tools and libraries, please visit the {doc}`MQT website <mqt:index>`.
For a full list of tools and libraries, please run the {doc}`MQT website <mqt:index>`.

```{include} ../README.md
:start-after: <!-- SPHINX-START -->
Expand Down
6 changes: 5 additions & 1 deletion include/Definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,16 @@ static constexpr fp PI_2 = static_cast<fp>(
1.570796326794896619231321691639751442098584699687552910487L);
static constexpr fp PI_4 = static_cast<fp>(
0.785398163397448309615660845819875721049292349843776455243L);
static constexpr fp TAU = static_cast<fp>(
6.283185307179586476925286766559005768394338798750211641950L);
static constexpr fp E = static_cast<fp>(
2.718281828459045235360287471352662497757247093699959574967L);

// forward declaration
class Operation;

// supported file formats
enum class Format { Real, OpenQASM, GRCS, TFC, QC, Tensor };
enum class Format { Real, OpenQASM, OpenQASM3, GRCS, TFC, QC, Tensor };

using DAG = std::vector<std::deque<std::unique_ptr<Operation>*>>;
using DAGIterator = std::deque<std::unique_ptr<Operation>*>::iterator;
Expand Down
1 change: 1 addition & 0 deletions include/QuantumComputation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class QuantumComputation {
std::unordered_set<sym::Variable> occuringVariables;

void importOpenQASM(std::istream& is);
void importOpenQASM3(std::istream& is);
void importReal(std::istream& is);
int readRealHeader(std::istream& is);
void readRealGateDescriptions(std::istream& is, int line);
Expand Down
54 changes: 54 additions & 0 deletions include/parsers/qasm3_parser/Gate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#pragma once

#include "NestedEnvironment.hpp"
#include "QuantumComputation.hpp"
#include "Statement.hpp"

namespace qasm3 {
struct GateInfo {
public:
size_t nControls;
size_t nTargets;
size_t nParameters;
qc::OpType type;
};

struct Gate {
public:
virtual ~Gate() = default;

virtual size_t getNControls() = 0;
virtual size_t getNTargets() = 0;
virtual size_t getNParameters() = 0;
};

struct StandardGate : public Gate {
public:
GateInfo info;

explicit StandardGate(GateInfo info) : info(info) {}

size_t getNControls() override { return info.nControls; }

size_t getNTargets() override { return info.nTargets; }
size_t getNParameters() override { return info.nParameters; }
};

struct CompoundGate : public Gate {
public:
std::vector<std::string> parameterNames;
std::vector<std::string> targetNames;
std::vector<std::shared_ptr<GateCallStatement>> body;

explicit CompoundGate(std::vector<std::string> parameterNames,
std::vector<std::string> targetNames,
std::vector<std::shared_ptr<GateCallStatement>> body)
: parameterNames(std::move(parameterNames)),
targetNames(std::move(targetNames)), body(std::move(body)) {}

size_t getNControls() override { return 0; }

size_t getNTargets() override { return targetNames.size(); }
size_t getNParameters() override { return parameterNames.size(); }
};
} // namespace qasm3
142 changes: 142 additions & 0 deletions include/parsers/qasm3_parser/InstVisitor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#pragma once

#include <any>
#include <iostream>
#include <map>
#include <sstream>
#include <utility>

namespace qasm3 {
class GateDeclaration;
class GateCallStatement;
class VersionDeclaration;
class DeclarationStatement;
class InitialLayout;
class OutputPermutation;
class AssignmentStatement;
class BarrierStatement;
class ResetStatement;

class Expression;
class BinaryExpression;
class UnaryExpression;
class IdentifierExpression;
class IdentifierList;
class Constant;
class MeasureExpression;

class InstVisitor {
public:
virtual void
visitGateStatement(std::shared_ptr<GateDeclaration> gateStatement) = 0;
virtual void visitVersionDeclaration(
std::shared_ptr<VersionDeclaration> versionDeclaration) = 0;
virtual void visitDeclarationStatement(
std::shared_ptr<DeclarationStatement> declarationStatement) = 0;
virtual void
visitInitialLayout(std::shared_ptr<InitialLayout> initialLayout) = 0;
virtual void visitOutputPermutation(
std::shared_ptr<OutputPermutation> outputPermutation) = 0;
virtual void visitGateCallStatement(
std::shared_ptr<GateCallStatement> gateCallStatement) = 0;
virtual void visitAssignmentStatement(
std::shared_ptr<AssignmentStatement> assignmentStatement) = 0;
virtual void
visitBarrierStatement(std::shared_ptr<BarrierStatement> barrierStatement) = 0;
virtual void
visitResetStatement(std::shared_ptr<ResetStatement> resetStatement) = 0;

virtual ~InstVisitor() = default;
};

class DefaultInstVisitor : public InstVisitor {
public:
void visitGateStatement(
std::shared_ptr<GateDeclaration> /*gateStatement*/) override {}
void visitVersionDeclaration(
std::shared_ptr<VersionDeclaration> /*versionDeclaration*/) override {}
void visitDeclarationStatement(
std::shared_ptr<DeclarationStatement> /*declarationStatement*/) override {
}
void visitInitialLayout(
std::shared_ptr<InitialLayout> /*initialLayout*/) override {}
void visitOutputPermutation(
std::shared_ptr<OutputPermutation> /*outputPermutation*/) override {}
void visitGateCallStatement(
std::shared_ptr<GateCallStatement> /*gateCallStatement*/) override {}
void visitAssignmentStatement(
std::shared_ptr<AssignmentStatement> /*assignmentStatement*/) override {}
void visitBarrierStatement(
std::shared_ptr<BarrierStatement> /*barrierStatement*/) override {}
void visitResetStatement(
std::shared_ptr<ResetStatement> /*resetStatement*/) override {}
};

template <typename T> class ExpressionVisitor {
public:
virtual T
visitBinaryExpression(std::shared_ptr<BinaryExpression> binaryExpression) = 0;
virtual T
visitUnaryExpression(std::shared_ptr<UnaryExpression> unaryExpression) = 0;
virtual T visitConstantExpression(std::shared_ptr<Constant> constant) = 0;
virtual T visitIdentifierExpression(
std::shared_ptr<IdentifierExpression> identifierExpression) = 0;
virtual T
visitIdentifierList(std::shared_ptr<IdentifierList> identifierList) = 0;
virtual T visitMeasureExpression(
std::shared_ptr<MeasureExpression> measureExpression) = 0;

// A manually implemented visitor function with a templated return type.
// This is not possible as a virtual function in expression, which is why
// we define it manually.
T visit(std::shared_ptr<Expression> expression) {
if (expression == nullptr) {
throw std::runtime_error("Expression is null");
}
if (auto binaryExpression =
std::dynamic_pointer_cast<BinaryExpression>(expression)) {
return visitBinaryExpression(binaryExpression);
}
if (auto unaryExpression =
std::dynamic_pointer_cast<UnaryExpression>(expression)) {
return visitUnaryExpression(unaryExpression);
}
if (auto constantInt = std::dynamic_pointer_cast<Constant>(expression)) {
return visitConstantExpression(constantInt);
}
if (auto identifierExpression =
std::dynamic_pointer_cast<IdentifierExpression>(expression)) {
return visitIdentifierExpression(identifierExpression);
}
if (auto identifierList =
std::dynamic_pointer_cast<IdentifierList>(expression)) {
return visitIdentifierList(identifierList);
}
if (auto measureExpression =
std::dynamic_pointer_cast<MeasureExpression>(expression)) {
return visitMeasureExpression(measureExpression);
}
throw std::runtime_error("Unhandled expression type.");
}

virtual ~ExpressionVisitor() = default;
};

template <typename T> class Type;
using ResolvedType = Type<uint64_t>;
class DesignatedType;
template <typename T> class UnsizedType;
template <typename T> class ArrayType;

template <typename T> class TypeVisitor {
public:
virtual ~TypeVisitor() = default;

virtual std::shared_ptr<ResolvedType>
visitDesignatedType(DesignatedType* designatedType) = 0;
virtual std::shared_ptr<ResolvedType>
visitUnsizedType(UnsizedType<T>* unsizedType) = 0;
virtual std::shared_ptr<ResolvedType>
visitArrayType(ArrayType<T>* arrayType) = 0;
};
} // namespace qasm3
29 changes: 29 additions & 0 deletions include/parsers/qasm3_parser/NestedEnvironment.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <map>
#include <string>
#include <vector>

template <typename T> class NestedEnvironment {
private:
std::vector<std::map<std::string, T>> env{};

public:
NestedEnvironment() { env.push_back({}); };

void push() { env.push_back({}); }

void pop() { env.pop_back(); }

std::optional<T> find(std::string key) {
for (auto it = env.rbegin(); it != env.rend(); ++it) {
auto found = it->find(key);
if (found != it->end()) {
return found->second;
}
}
return std::nullopt;
}

void emplace(std::string key, T value) { env.back().emplace(key, value); }
};
Loading

0 comments on commit ef86fb2

Please sign in to comment.