Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable v3 MVP to be used from Python #169

Merged
merged 33 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f7b48a3
Defined V1xAnalyzer and V3xAnalyzer in python/module/cqasm/{v1x,v3x}.
rturrado Nov 14, 2023
9ea3b59
Minor aesthetic change for setting SWIG_FILE.
rturrado Nov 14, 2023
c430589
API is now analyze_file and analyze_string.
rturrado Nov 14, 2023
00f33cd
Renamed 'a' to 'analyzer' for V1xAnalyzer and V3xAnalyzer.
rturrado Nov 14, 2023
aab4937
Added 'cqasm.v3x' package to the list of packages in setup.py.
rturrado Nov 14, 2023
d0d9644
Renamed libdir to lib_dir.
rturrado Nov 14, 2023
9d2fff3
Applied some clang-tidy suggestions.
rturrado Nov 14, 2023
4758032
Initialized members in the order in which they are defined, as sugges…
rturrado Nov 14, 2023
1ae0033
Sorted list of directories.
rturrado Nov 14, 2023
0cf8532
Changed test classes to start with 'Test'.
rturrado Nov 14, 2023
f8b218e
Added 'v3x/cqasm-py.hpp' to libQasm.i.
rturrado Nov 14, 2023
72f315f
Created test/v3x/{cpp,python} folders.
rturrado Nov 14, 2023
bb87ccd
Changed pyproject.toml to pytest.ini.
rturrado Nov 14, 2023
c5ae663
Moved test/v10/python/test_init.py to 'test', and added 'test/v3x/pyt…
rturrado Nov 24, 2023
9b20741
Trying to fix GitHub Actions Python jobs.
rturrado Nov 26, 2023
778b44d
Trying to fix GitHub Actions Python (macos-latest) job.
rturrado Nov 26, 2023
48468ee
Trying to fix GitHub Actions Python (macos-latest) job.
rturrado Nov 26, 2023
d9c66f4
Trying to fix GitHub Actions Python (macos-latest) job.
rturrado Nov 26, 2023
5334247
Added array versions for all the gates in the default analyzer.
rturrado Nov 28, 2023
644132b
test_parse_string is now recognized when running pytest.
rturrado Nov 28, 2023
f76917c
Merge branch 'develop' into v3-mvp-python
rturrado Nov 28, 2023
6aa2491
register_instruction only admits 2 parameters for v3x.
rturrado Nov 28, 2023
4560a40
Fixed issue: `AttributeError: 'string' object has no attribute 'encode'.
rturrado Nov 29, 2023
99080f6
Fixed python/module/cqasm/{v1x,v3x}/__init__.py.
rturrado Nov 29, 2023
858c617
Fixed src/{v1x,v3x}/cqasm-py.cpp.
rturrado Nov 29, 2023
31ca6db
Moved test_init.py back to test/v10/python.
rturrado Nov 29, 2023
0db9253
Fixed python/module/cqasm/v3x/__init__.py analyze_file and analyze_s…
rturrado Nov 29, 2023
e363f68
Fixed circular imports in python/module/cqasm/{v1x,v3x}/primitives.py.
rturrado Nov 29, 2023
cf1cec5
Fixed param types for measure instruction at src/v3x/cqasm.cpp defaul…
rturrado Nov 29, 2023
1328cf2
Implemented a few V3xAnalyzer tests.
rturrado Nov 29, 2023
07b5fc7
Removed references to Python 2, as it is unsupported.
rturrado Dec 5, 2023
7078860
Merge branch 'develop' into v3-mvp-python
rturrado Dec 5, 2023
8581beb
Updated parse_file and analyze_file comments.
rturrado Dec 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
with:
python-version: "3.11"
- name: Install Python dependencies
run: python -m pip install --upgrade pip numpy pytest setuptools wheel
run: python -m pip install --upgrade pip conan numpy pytest setuptools wheel
- name: Install SWIG, and set build type (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
Expand Down
5 changes: 4 additions & 1 deletion include/v10/libQasm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@

class libQasm {
public:
libQasm() : parse_result_{ 0 }, qasm_rep_{} {}
libQasm()
: qasm_rep_{}
, parse_result_{ 0 }
{}

void parse_string(const std::string &qasm_str) {
compiler::QasmSemanticChecker sm(qasm_str);
Expand Down
4 changes: 2 additions & 2 deletions include/v1x/cqasm-analyzer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,13 @@ class Analyzer {
/**
* Parses and analyzes the given file.
*/
AnalysisResult analyze(const std::string &filename) const;
AnalysisResult analyze_file(const std::string &filename) const;

/**
* Parses and analyzes the given file pointer.
* The optional filename argument will be used only for error messages.
*/
AnalysisResult analyze(FILE *file, const std::string &filename = "<unknown>") const;
AnalysisResult analyze_file(FILE *file, const std::string &filename = "<unknown>") const;

/**
* Parses and analyzes the given string.
Expand Down
18 changes: 13 additions & 5 deletions include/v1x/cqasm-py.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <string>
#include <vector>


// Forward declarations for internal types.
namespace cqasm::v1x::analyzer { class Analyzer; }

Expand All @@ -23,7 +24,7 @@ class V1xAnalyzer {
/**
* Reference to the actual C++ analyzer that this wraps.
*/
std::unique_ptr<cqasm::v1x::analyzer::Analyzer> a;
std::unique_ptr<cqasm::v1x::analyzer::Analyzer> analyzer;

public:
/**
Expand All @@ -41,6 +42,13 @@ class V1xAnalyzer {
bool without_defaults = false
);

/**
* std::unique_ptr<T> requires T to be a complete class for the ~T operation.
* Since we are using a forward declaration for Analyzer, we need to declare ~T in the header file,
* and implement it in the source file.
*/
~V1xAnalyzer();

/**
* Registers an instruction type.
* The arguments are passed straight to instruction::Instruction's constructor.
Expand All @@ -67,9 +75,9 @@ class V1xAnalyzer {
* Only parses the given file.
* The file must be in v1.x syntax.
* No version check or conversion is performed.
* Returns a vector of strings,
* of which the first is always present and is the CBOR serialization of the v1.x AST.
* Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v1.x AST.
* Any additional strings represent error messages.
* Notice that the AST and error messages won't be available at the same time.
*/
static std::vector<std::string> parse_file(
const std::string &filename
Expand All @@ -89,9 +97,9 @@ class V1xAnalyzer {
* If the file is written in a later file version,
* this function may try to reduce it to the maximum v1.x API version support advertised
* using this object's constructor.
* Returns a vector of strings,
* of which the first is always present and is the CBOR serialization of the v1.x semantic tree.
* Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v1.x semantic tree.
* Any additional strings represent error messages.
* Notice that the AST and error messages won't be available at the same time.
*/
std::vector<std::string> analyze_file(
const std::string &filename
Expand Down
4 changes: 2 additions & 2 deletions include/v1x/cqasm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace v1x {
* Parses and analyzes the given file path with the default analyzer,
* dumping error messages to stderr and throwing an analyzer::AnalysisFailed on failure.
*/
tree::One<semantic::Program> analyze(
tree::One<semantic::Program> analyze_file(
const std::string &file_path,
const std::string &api_version = "1.0"
);
Expand All @@ -35,7 +35,7 @@ tree::One<semantic::Program> analyze(
* error messages to stderr and throwing an analyzer::AnalysisFailed on failure.
* The optional file_name is only used for error messages.
*/
tree::One<semantic::Program> analyze(
tree::One<semantic::Program> analyze_file(
FILE *fp,
const std::string &file_name = "<unknown>",
const std::string &api_version = "1.0"
Expand Down
7 changes: 3 additions & 4 deletions include/v3x/BuildCustomAstVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
#include "cqasm-ast.hpp"
#include "v3x/CqasmParser.h"
#include "v3x/CqasmParserVisitor.h"
#include "v3x/CustomErrorListener.hpp"

#include <antlr4-runtime.h> // Token


#include <any>

namespace antlr4 { class Token; }
namespace cqasm::v3x::parser { class CustomErrorListener; }


namespace cqasm::v3x::parser {

Expand Down
4 changes: 2 additions & 2 deletions include/v3x/BuildTreeGenAstVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
#include "v3x/BuildCustomAstVisitor.hpp"
#include "v3x/CqasmParser.h"
#include "v3x/CqasmParserVisitor.h"
#include "v3x/CustomErrorListener.hpp"

#include <any>

namespace cqasm::v3x::parser { class CustomErrorListener; }


namespace cqasm::v3x::parser {

Expand Down
5 changes: 4 additions & 1 deletion include/v3x/ScannerAntlr.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#pragma once

#include "v3x/BuildCustomAstVisitor.hpp"
#include "v3x/CustomErrorListener.hpp"
#include "v3x/cqasm-parse-result.hpp"

#include <memory> // unique_ptr
#include <string>

namespace antlr4 { class ANTLRInputStream; }
namespace cqasm::v3x::parser { class CustomErrorListener; }


namespace cqasm::v3x::parser {

Expand Down
2 changes: 1 addition & 1 deletion include/v3x/cqasm-analyzer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class Analyzer {
/**
* Parses and analyzes the given file.
*/
[[nodiscard]] AnalysisResult analyze(const std::string &filename);
[[nodiscard]] AnalysisResult analyze_file(const std::string &filename);

/**
* Parses and analyzes the given string.
Expand Down
1 change: 0 additions & 1 deletion include/v3x/cqasm-parse-helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "v3x/cqasm-parse-result.hpp"
#include "v3x/ScannerAntlr.hpp"

#include <antlr4-runtime.h>
#include <memory> // unique_ptr
#include <string>

Expand Down
22 changes: 15 additions & 7 deletions include/v3x/cqasm-py.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <string>
#include <vector>


// Forward declarations for internal types.
namespace cqasm::v3x::analyzer { class Analyzer; }

Expand All @@ -23,7 +24,7 @@ class V3xAnalyzer {
/**
* Reference to the actual C++ analyzer that this wraps.
*/
std::unique_ptr<cqasm::v3x::analyzer::Analyzer> a;
std::unique_ptr<cqasm::v3x::analyzer::Analyzer> analyzer;

public:
/**
Expand All @@ -36,11 +37,18 @@ class V3xAnalyzer {
* the initial mappings and functions are not configurable at all.
* The defaults for these are always used.
*/
V3xAnalyzer(
explicit V3xAnalyzer(
const std::string &max_version = "3.0",
bool without_defaults=false
bool without_defaults = false
);

/**
* std::unique_ptr<T> requires T to be a complete class for the ~T operation.
* Since we are using a forward declaration for Analyzer, we need to declare ~T in the header file,
* and implement it in the source file.
*/
~V3xAnalyzer();

/**
* Registers an instruction type.
* The arguments are passed straight to instruction::Instruction's constructor.
Expand All @@ -51,9 +59,9 @@ class V3xAnalyzer {
* Only parses the given file.
* The file must be in v3.x syntax.
* No version check or conversion is performed.
* Returns a vector of strings,
* of which the first is always present and is the CBOR serialization of the v3.x AST.
* Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v3.x AST.
* Any additional strings represent error messages.
* Notice that the AST and error messages won't be available at the same time.
*/
static std::vector<std::string> parse_file(
const std::string &filename
Expand All @@ -73,9 +81,9 @@ class V3xAnalyzer {
* If the file is written in a later file version,
* this function may try to reduce it to the maximum v3.x API version support advertised
* using this object's constructor.
* Returns a vector of strings,
* of which the first is always present and is the CBOR serialization of the v3.x semantic tree.
* Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v3.x semantic tree.
* Any additional strings represent error messages.
* Notice that the AST and error messages won't be available at the same time.
*/
std::vector<std::string> analyze_file(
const std::string &filename
Expand Down
2 changes: 1 addition & 1 deletion include/v3x/cqasm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace v3x {
* Parses and analyzes the given file path with the default analyzer,
* dumping error messages to stderr and throwing an analyzer::AnalysisFailed on failure.
*/
tree::One<cqasm::v3x::semantic::Program> analyze(
tree::One<cqasm::v3x::semantic::Program> analyze_file(
const std::string &file_path,
const std::string &api_version = "3.0"
);
Expand Down
4 changes: 0 additions & 4 deletions pyproject.toml

This file was deleted.

5 changes: 5 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[pytest]
testpaths =
"test/v10/python"
"test/v3x/python"
python_files = test_*.py
4 changes: 3 additions & 1 deletion python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ set(CMAKE_CXX_EXTENSIONS OFF)
#=============================================================================#

# Configure SWIG.
set(SWIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/libQasm.i")
set(SWIG_FILE
"${CMAKE_CURRENT_SOURCE_DIR}/libQasm.i"
)

set_source_files_properties("${SWIG_FILE}" PROPERTIES
CPLUSPLUS ON
Expand Down
29 changes: 14 additions & 15 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,21 @@ aside from the `setup.py` file living in the root directory.

File/directory list:

- `libQasm.i`: SWIG directives for the bindings.
- `CMakeLists.txt`: SWIG and the Python extension build are handled by CMake,
so it can make everything's linked together properly.
Don't use this file directly.
It's intended to be added by the root `CMakeLists.txt`,
and only when the build is orchestrated by `setup.py`.

- `libQasm`: represents the Python module excluding the extension. Any Python
files in here will be included in the Python install.
- `conda`: contains the conda recipe for libqasm,
in case you're using that rather than pip to manage your Python packages.
It mostly just defers to `setup.py`,
but will help you set up the build dependencies regardless of your platform.

- `conda`: contains the conda recipe for libqasm, in case you're using that
rather than pip to manage your Python packages. It mostly just defers to
`setup.py`, but will help you set up the build dependencies regardless of
your platform.
- `libQasm`: represents the Python module excluding the extension.
Any Python files in here will be included in the Python install.

- `CMakeLists.txt`: SWIG and the Python extension build are handled by CMake,
so it can make everything's linked together properly. Don't use this file
directly; it's intended to be added by the root `CMakeLists.txt`, and only
when the build is orchestrated by `setup.py`.

- `python_lib.py`: helper script for CMake to find the Python library to link
against, because FindPYTHON often picks the wrong one, especially in venvs.
- `libQasm.i`: SWIG directives for the bindings.

- `compat`: helper scripts for CMake to make old CMake versions work.
- `python_lib.py`: helper script for CMake to find the Python library to link against,
because FindPYTHON often picks the wrong one, especially in virtual environments.
2 changes: 2 additions & 0 deletions python/libQasm.i
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "v10/qasm_ast.hpp"
#include "v10/libQasm.hpp"
#include "v1x/cqasm-py.hpp"
#include "v3x/cqasm-py.hpp"
%}

%include "exception.i"
Expand Down Expand Up @@ -49,6 +50,7 @@ namespace std {
%include "v10/qasm_ast.hpp"
%include "v10/libQasm.hpp"
%include "v1x/cqasm-py.hpp"
%include "v3x/cqasm-py.hpp"

namespace std {
%template(subcircuit_vector) vector<shared_ptr<compiler::SubCircuit>>;
Expand Down
48 changes: 30 additions & 18 deletions python/module/cqasm/v1x/__init__.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,46 @@
import libQasm;
import libQasm


class Analyzer(libQasm.V1xAnalyzer):

@staticmethod
def parse_file(*args):
retval = libQasm.V1xAnalyzer.parse_file(*args)
if len(retval) == 1:
ret = libQasm.V1xAnalyzer.parse_file(*args)
if len(ret) == 1:
import cqasm.v1x.ast as ast
return ast.Root.deserialize(retval[0].encode("utf-8", errors="surrogateescape"))
return list(retval[1:])
serialized_ast_str = str(ret[0])
serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape")
deserialized_ast = ast.Root.deserialize(serialized_ast_bytes)
return deserialized_ast
return [str(error) for error in ret[1:]]

rturrado marked this conversation as resolved.
Show resolved Hide resolved
@staticmethod
def parse_string(*args):
retval = libQasm.V1xAnalyzer.parse_string(*args)
if len(retval) == 1:
ret = libQasm.V1xAnalyzer.parse_string(*args)
if len(ret) == 1:
import cqasm.v1x.ast as ast
return ast.Root.deserialize(retval[0].encode("utf-8", errors="surrogateescape"))
return list(retval[1:])
serialized_ast_str = str(ret[0])
serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape")
deserialized_ast = ast.Root.deserialize(serialized_ast_bytes)
return deserialized_ast
return [str(error) for error in ret[1:]]

def analyze_file(self, *args):
retval = super().analyze_file(*args)
if len(retval) == 1:
ret = super().analyze_file(*args)
if len(ret) == 1:
import cqasm.v1x.semantic as semantic
print(retval[0].encode("utf-8", errors="surrogateescape"))
return semantic.Program.deserialize(retval[0].encode("utf-8", errors="surrogateescape"))
return list(retval[1:])
serialized_ast_str = str(ret[0])
serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape")
deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes)
return deserialized_ast
return [str(error) for error in ret[1:]]

def analyze_string(self, *args):
retval = super().analyze_string(*args)
if len(retval) == 1:
ret = super().analyze_string(*args)
if len(ret) == 1:
import cqasm.v1x.semantic as semantic
return semantic.Program.deserialize(retval[0].encode("utf-8", errors="surrogateescape"))
return list(retval[1:])
serialized_ast_str = str(ret[0])
serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape")
deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes)
return deserialized_ast
return [str(error) for error in ret[1:]]
Loading
Loading