Skip to content

Commit

Permalink
Merge pull request #18 from QuTech-Delft/9-implement-dev-tools-and-do…
Browse files Browse the repository at this point in the history
…cument-usage

9 implement dev tools and document usage
  • Loading branch information
elenbaasc authored Nov 22, 2023
2 parents 14c831c + ae9eaa3 commit 8e3c6e4
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 33 deletions.
35 changes: 34 additions & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,39 @@

### Tools

**TODO**: Describe use of the devcontainer (PyCharm, VS Code)

#### Poetry

Project dependencies are specified in the `pyproject.toml` file in the root directory of the project.

Website: <https://python-poetry.org/>

#### MkDocs


Install dependencies

```shell
$ poetry install
```

Start a Poetry shell

```shell
$ poetry shell
```

Within the shell PyTest and MyPy can be run accordingly:

```shell
$ mypy -p opensquirrel
```

```shell
$ pytest
```

##### MkDocs

The documentation is generated using MkDocs. For full documentation visit [mkdocs.org](https://www.mkdocs.org).

Expand All @@ -23,3 +49,10 @@ The documentation is generated using MkDocs. For full documentation visit [mkdoc
* `mkdocs serve` - Start the live-reloading docs server.
* `mkdocs build` - Build the documentation site.
* `mkdocs -h` - Print help message and exit.

#### MyPy

Check Python typing by running the following command in the root directory



13 changes: 7 additions & 6 deletions opensquirrel/Circuit.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import antlr4
import numpy as np

from opensquirrel.DefaultGates import DefaultGates # For the doctest.
from opensquirrel.McKayDecomposer import McKayDecomposer
Expand Down Expand Up @@ -46,7 +47,7 @@ def __init__(self, squirrelAST: SquirrelAST):
self.squirrelAST = squirrelAST

@classmethod
def from_string(cls, gates, cqasm3_string):
def from_string(cls, gates: dict, cqasm3_string: str):
"""Create a circuit object from a cQasm3 string. All the gates in the circuit need to be defined in
the `gates` argument.
Expand Down Expand Up @@ -76,10 +77,10 @@ def from_string(cls, gates, cqasm3_string):

return Circuit(squirrelASTCreator.visit(tree))

def getNumberOfQubits(self):
def getNumberOfQubits(self) -> int:
return self.squirrelAST.nQubits

def getQubitRegisterName(self):
def getQubitRegisterName(self) -> str:
return self.squirrelAST.qubitRegisterName

def decompose_mckay(self):
Expand All @@ -96,7 +97,7 @@ def decompose_mckay(self):
mcKayDecomposer = McKayDecomposer(self.gates)
self.squirrelAST = mcKayDecomposer.process(self.squirrelAST)

def replace(self, gateName, f):
def replace(self, gateName: str, f):
"""Manually replace occurrences of a given gate with a list of gates.
* this can be called decomposition - but it's the least fancy version of it
Expand All @@ -107,7 +108,7 @@ def replace(self, gateName, f):
replacer = Replacer(self.gates) # FIXME: only one instance of this is needed.
self.squirrelAST = replacer.process(self.squirrelAST, gateName, f)

def test_get_circuit_matrix(self):
def test_get_circuit_matrix(self) -> np.ndarray:
"""Get the (large) unitary matrix corresponding to the circuit.
* this matrix has 4**n elements, where n is the number of qubits
Expand All @@ -118,7 +119,7 @@ def test_get_circuit_matrix(self):
interpreter = TestInterpreter(self.gates)
return interpreter.process(self.squirrelAST)

def __repr__(self):
def __repr__(self) -> str:
"""Write the circuit to a cQasm3 string.
* comments are removed
Expand Down
4 changes: 2 additions & 2 deletions opensquirrel/CircuitBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class CircuitBuilder:

__default_qubit_register_name = "q"

def __init__(self, gates, numberOfQubits):
def __init__(self, gates: dict, numberOfQubits: int):
self.squirrelAST = SquirrelAST(gates, numberOfQubits, self.__default_qubit_register_name)

def __getattr__(self, attr):
Expand All @@ -28,5 +28,5 @@ def addThisGate(*args):

return addComment if attr == "comment" else addThisGate

def to_circuit(self):
def to_circuit(self) -> Circuit:
return Circuit(self.squirrelAST)
10 changes: 3 additions & 7 deletions opensquirrel/Common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cmath
import math
from enum import Enum
from typing import Tuple

import numpy as np

Expand All @@ -19,7 +20,7 @@ class ArgType(Enum):
INT = 2


def exprTypeToArgType(t):
def exprTypeToArgType(t: ExprType) -> ArgType:
if t == ExprType.QUBITREFS:
return ArgType.QUBIT
if t == ExprType.FLOAT:
Expand All @@ -28,17 +29,12 @@ def exprTypeToArgType(t):
return ArgType.INT


class Parameter:
def __init__(self, n):
self.value = n


X = np.array([[0, 1], [1, 0]])
Y = np.array([[0, -1j], [1j, 0]])
Z = np.array([[1, 0], [0, -1]])


def Can1(axis, angle, phase=0):
def Can1(axis: Tuple[float, float, float], angle: float, phase: float = 0) -> np.ndarray:
nx, ny, nz = axis
norm = math.sqrt(nx**2 + ny**2 + nz**2)
assert norm > 0.00000001
Expand Down
10 changes: 6 additions & 4 deletions opensquirrel/Gates.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Tuple

import numpy as np

from opensquirrel.Common import ArgType
Expand All @@ -8,7 +10,7 @@ class Semantic:


class SingleQubitAxisAngleSemantic(Semantic):
def __init__(self, axis: (float, float, float), angle: float, phase: float):
def __init__(self, axis: Tuple[float, float, float], angle: float, phase: float):
self.axis = self._normalize(np.array(axis).astype(np.float64))
self.angle = angle
self.phase = phase
Expand All @@ -29,7 +31,7 @@ def __init__(self, numberOfControlQubits: int, matrix: np.ndarray):
pass # TODO


def queryEntry(gatesDict, gateName):
def queryEntry(gatesDict: dict, gateName: str):
if gateName not in gatesDict:
raise Exception(f"Unknown gate or alias of gate: `{gateName}`")

Expand All @@ -41,7 +43,7 @@ def queryEntry(gatesDict, gateName):
return entry


def querySemantic(gatesDict, gateName, *gateArgs):
def querySemantic(gatesDict: dict, gateName: str, *gateArgs):
signature = querySignature(gatesDict, gateName)
assert len(gateArgs) == sum(1 for t in signature if t != ArgType.QUBIT)

Expand All @@ -59,7 +61,7 @@ def querySemantic(gatesDict, gateName, *gateArgs):
return semantic(*gateArgs) # TODO: nice error when args don't match? But should be already checked by typer


def querySignature(gatesDict, gateName: str):
def querySignature(gatesDict: dict, gateName: str):
entry = queryEntry(gatesDict, gateName)

assert "signature" in entry, f"Gate signature not defined for gate: `{gateName}`"
Expand Down
4 changes: 2 additions & 2 deletions opensquirrel/MatrixExpander.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import numpy as np

from opensquirrel.Common import Can1
from opensquirrel.Gates import MultiQubitMatrixSemantic, SingleQubitAxisAngleSemantic
from opensquirrel.Gates import MultiQubitMatrixSemantic, Semantic, SingleQubitAxisAngleSemantic


# This should only be used for testing and on circuits with low number of qubits.
def getBigMatrix(semantic, qubitOperands, totalQubits):
def getBigMatrix(semantic: Semantic, qubitOperands, totalQubits):
if isinstance(semantic, SingleQubitAxisAngleSemantic):
whichQubit = qubitOperands[0]

Expand Down
5 changes: 3 additions & 2 deletions opensquirrel/McKayDecomposer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from math import acos, atan2, cos, pi, sin, sqrt
from typing import Tuple

import numpy as np

Expand All @@ -7,7 +8,7 @@
from opensquirrel.SquirrelAST import SquirrelAST


def normalizeAngle(x):
def normalizeAngle(x: float) -> float:
t = x - 2 * pi * (x // (2 * pi) + 1)
if t < -pi + ATOL:
t += 2 * pi
Expand All @@ -23,7 +24,7 @@ def __init__(self, gates):
queryEntry(self.gates, "rz") # FIXME: improve. Pass those gates as parameters to the constructor.
queryEntry(self.gates, "x90")

def _decomposeAndAdd(self, qubit, angle, axis):
def _decomposeAndAdd(self, qubit, angle: float, axis: Tuple[float, float, float]):
if abs(angle) < ATOL:
return

Expand Down
12 changes: 7 additions & 5 deletions opensquirrel/SquirrelAST.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from typing import Any

from opensquirrel.Gates import querySignature


class SquirrelAST:
# This is just a list of gates (for now?)
def __init__(self, gates, nQubits, qubitRegisterName):
def __init__(self, gates, nQubits: int, qubitRegisterName: str):
self.gates = gates
self.nQubits = nQubits
self.operations = []
self.qubitRegisterName = qubitRegisterName
self.nQubits: int = nQubits
self.operations: list[Any] = []
self.qubitRegisterName: str = qubitRegisterName

def addGate(self, gateName, *interpretedArgs):
def addGate(self, gateName: str, *interpretedArgs):
signature = querySignature(self.gates, gateName)
assert len(signature) == len(interpretedArgs), f"Wrong number of arguments for gate `{gateName}`"

Expand Down
55 changes: 51 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ coverage = {extras = ["toml"], version = "^7.3.2"}
isort = "^5.11.4"
pytest = {extras = ["toml"], version = "^7.4.3"}
pytest-cov = "^4.1.0"
mypy = "^1.7.0"

[tool.pytest.ini_options]
addopts = "-v --cov --cov-report term-missing:skip-covered --cov-report xml"
Expand Down Expand Up @@ -74,6 +75,9 @@ line_length = 120
[tool.black]
line-length = 120

[tool.mypy]
ignore_missing_imports = true

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

0 comments on commit 8e3c6e4

Please sign in to comment.