-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Implement ControlledSemantic to be able to express CNOT as a controlled X, for instance - Separate validation of qubit ranges from type-checking in a separate ANTLR tree visitor - snake_case instead of camelCase for variable names - Add docstrings to parsing classes - The GateLibrary superclass is used to factorize code for gateset-aware classes (e.g. TypeChecker) - Semantic classes are removed, absorbed into Gate subclasses - Move ALL ANTLR parsing classes to parsing folder - this has already been done, but only partially - Gates are specified directly with Python functions and a decorator - Lay the basis of handling of anonymous gates - Writer turned into impl pattern - Rename AST -> IR - Make test_testinterpreter a proper unit test, before it was testing parsing too - Visitor pattern for the SquirrelIR class - Use those visitors in e.g. writer and test_interpreter - Various code fixes - Use inspect to know Python function signatures This makes the gate semantic API nice to use from Python.
- Loading branch information
Showing
38 changed files
with
1,342 additions
and
1,087 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
from opensquirrel.circuit import Circuit | ||
from opensquirrel.circuit_builder import CircuitBuilder | ||
from opensquirrel.default_gates import DefaultGates | ||
from opensquirrel.default_gates import default_gate_aliases |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,60 @@ | ||
import inspect | ||
from typing import Callable, Dict | ||
|
||
from opensquirrel.circuit import Circuit | ||
from opensquirrel.default_gates import DefaultGates | ||
from opensquirrel.squirrel_ast import SquirrelAST | ||
from opensquirrel.default_gates import default_gate_aliases, default_gate_set | ||
from opensquirrel.gate_library import GateLibrary | ||
from opensquirrel.squirrel_ir import Comment, Gate, Qubit, SquirrelIR | ||
|
||
|
||
class CircuitBuilder: | ||
"""A class using the builder pattern to make construction of circuits easy. | ||
class CircuitBuilder(GateLibrary): | ||
""" | ||
A class using the builder pattern to make construction of circuits easy from Python. | ||
Adds corresponding gate when a method is called. Checks gates are known and called with the right arguments. | ||
Mainly here to allow for Qiskit-style circuit construction: | ||
>>> myCircuit = CircuitBuilder(DefaultGates, 3).h(0).cnot(0, 1).cnot(0, 2).to_circuit() | ||
>>> CircuitBuilder(number_of_qubits=3).h(Qubit(0)).cnot(Qubit(0), Qubit(1)).cnot(Qubit(0), Qubit(2)).to_circuit() | ||
version 3.0 | ||
<BLANKLINE> | ||
qubit[3] q | ||
<BLANKLINE> | ||
h q[0] | ||
cnot q[0], q[1] | ||
cnot q[0], q[2] | ||
<BLANKLINE> | ||
""" | ||
|
||
__default_qubit_register_name = "q" | ||
_default_qubit_register_name = "q" | ||
|
||
def __init__(self, gates: dict, numberOfQubits: int): | ||
self.squirrelAST = SquirrelAST(gates, numberOfQubits, self.__default_qubit_register_name) | ||
def __init__( | ||
self, | ||
number_of_qubits: int, | ||
gate_set: [Callable[..., Gate]] = default_gate_set, | ||
gate_aliases: Dict[str, Callable[..., Gate]] = default_gate_aliases, | ||
): | ||
GateLibrary.__init__(self, gate_set, gate_aliases) | ||
self.squirrel_ir = SquirrelIR( | ||
number_of_qubits=number_of_qubits, qubit_register_name=self._default_qubit_register_name | ||
) | ||
|
||
def __getattr__(self, attr): | ||
def addComment(commentString: str): | ||
self.squirrelAST.addComment(commentString) | ||
def add_comment(comment_string: str): | ||
self.squirrel_ir.add_comment(Comment(comment_string)) | ||
return self | ||
|
||
def addThisGate(*args): | ||
self.squirrelAST.addGate(attr, *args) | ||
def add_this_gate(*args): | ||
generator_f = GateLibrary.get_gate_f(self, attr) | ||
|
||
for i, par in enumerate(inspect.signature(generator_f).parameters.values()): | ||
if not isinstance(args[i], par.annotation): | ||
raise TypeError( | ||
f"Wrong argument type for gate `{attr}`, got {type(args[i])} but expected {par.annotation}" | ||
) | ||
|
||
self.squirrel_ir.add_gate(generator_f(*args)) | ||
return self | ||
|
||
return addComment if attr == "comment" else addThisGate | ||
return add_comment if attr == "comment" else add_this_gate | ||
|
||
def to_circuit(self) -> Circuit: | ||
return Circuit(self.squirrelAST) | ||
return Circuit(self.squirrel_ir) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import numpy as np | ||
|
||
from opensquirrel.squirrel_ir import Comment, Gate, SquirrelIR, SquirrelIRVisitor | ||
from opensquirrel.utils.matrix_expander import get_matrix | ||
|
||
|
||
class _CircuitMatrixCalculator(SquirrelIRVisitor): | ||
def __init__(self, number_of_qubits): | ||
self.number_of_qubits = number_of_qubits | ||
self.matrix = np.eye(1 << self.number_of_qubits, dtype=np.complex128) | ||
|
||
def visit_gate(self, gate: Gate): | ||
big_matrix = get_matrix(gate, number_of_qubits=self.number_of_qubits) | ||
self.matrix = big_matrix @ self.matrix | ||
|
||
def visit_comment(self, comment: Comment): | ||
pass | ||
|
||
|
||
def get_circuit_matrix(squirrel_ir: SquirrelIR): | ||
""" | ||
Compute the Numpy unitary matrix corresponding to the circuit. | ||
The size of this matrix grows exponentially with the number of qubits. | ||
""" | ||
|
||
impl = _CircuitMatrixCalculator(squirrel_ir.number_of_qubits) | ||
|
||
squirrel_ir.accept(impl) | ||
|
||
return impl.matrix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.