Skip to content

Commit

Permalink
Merge pull request #112 from BQSKit/1.0.4-dev
Browse files Browse the repository at this point in the history
1.0.4
  • Loading branch information
edyounis authored Jan 23, 2023
2 parents cfc44ec + fab1804 commit 5d46cda
Show file tree
Hide file tree
Showing 24 changed files with 377 additions and 94 deletions.
17 changes: 10 additions & 7 deletions .github/workflows/tox.yml → .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
name: tox
name: tests

on:
pull_request:
push:
branches: [master]

jobs:
tox:
tests:
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10']
python-version: ['3.8', '3.9', '3.10', '3.11']
os: [macOS-latest, windows-latest, ubuntu-latest]

runs-on: ${{ matrix.os }}
Expand All @@ -18,9 +18,12 @@ jobs:
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: install tox
run: python -m pip install --upgrade tox virtualenv setuptools pip
- name: run tox
- name: Upgrade python environment
run: python -m pip install --upgrade virtualenv setuptools pip
- name: Install BQSKit
env:
SYSTEM_VERSION_COMPAT: 0
NUMBER_RANDOM_CIRCUITS: 100
run: tox -e py
run: pip install '.[ext,dev]'
- name: Run tests
run: pytest
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ repos:
- --in-place
- --max-line-length=80
- --ignore=E731
exclude: 'tests/ext.*'
- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
hooks:
Expand All @@ -54,6 +55,7 @@ repos:
- --add-import
- from __future__ import annotations
- --py37-plus
exclude: 'tests/ext.*'
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.4.0
hooks:
Expand Down
28 changes: 8 additions & 20 deletions bqskit/ext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,26 @@
"""
from __future__ import annotations

try:
import cirq # noqa
import pytket # noqa
import qiskit # noqa
import qutip # noqa
except ImportError as e:
raise ImportError(
'\n\nUnable to import bqskit.ext package.\n'
'Ensure that bqskit was installed with extension support.\n'
'To install bqskit with extension support try:\n'
'\tpip install bqskit[ext]\n',
) from e

from bqskit.ext.cirq.models import Sycamore23Model
from bqskit.ext.cirq.models import SycamoreModel
from bqskit.ext.cirq.translate import bqskit_to_cirq
from bqskit.ext.cirq.translate import cirq_to_bqskit
from bqskit.ext.honeywell import H1_1Model
from bqskit.ext.honeywell import H1_2Model
from bqskit.ext.pytket.translate import bqskit_to_pytket
from bqskit.ext.pytket.translate import pytket_to_bqskit
from bqskit.ext.qiskit.models import model_from_backend
from bqskit.ext.qiskit.translate import bqskit_to_qiskit
from bqskit.ext.qiskit.translate import qiskit_to_bqskit
from bqskit.ext.qutip.translate import bqskit_to_qutip
from bqskit.ext.qutip.translate import qutip_to_bqskit
from bqskit.ext.supermarq import supermarq_program_communication
from bqskit.ext.rigetti import Aspen11Model
from bqskit.ext.rigetti import AspenM2Model
from bqskit.ext.supermarq import supermarq_critical_depth
from bqskit.ext.supermarq import supermarq_entanglement_ratio
from bqskit.ext.supermarq import supermarq_parallelism
from bqskit.ext.supermarq import supermarq_liveness
from bqskit.ext.rigetti import Aspen11Model
from bqskit.ext.rigetti import AspenM2Model
from bqskit.ext.honeywell import H1_1Model
from bqskit.ext.honeywell import H1_2Model
from bqskit.ext.cirq.models import Sycamore23Model, SycamoreModel
from bqskit.ext.supermarq import supermarq_parallelism
from bqskit.ext.supermarq import supermarq_program_communication


__all__ = [
Expand Down
32 changes: 22 additions & 10 deletions bqskit/ext/cirq/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""This module implements pre-built models for Google's QPUs."""
from __future__ import annotations

import cirq_google

from bqskit.compiler.machine import MachineModel
from bqskit.ir.gate import Gate
from bqskit.ir.gates import CZGate
Expand All @@ -21,18 +19,32 @@
}

# Sycamore Device
_qubits = cirq_google.Sycamore.metadata.qubit_set
_qubit_map = {q: i for i, q in enumerate(list(_qubits))}
_pairs = cirq_google.Sycamore.metadata.qubit_pairs
_edges = [(_qubit_map[q1], _qubit_map[q2]) for q1, q2 in _pairs]
_edges = [
(20, 14), (34, 26), (35, 20), (8, 3), (8, 17), (47, 16),
(36, 28), (48, 28), (43, 38), (38, 14), (12, 6), (47, 12),
(46, 31), (48, 11), (24, 18), (30, 52), (24, 33), (0, 50),
(8, 33), (45, 14), (34, 18), (7, 31), (48, 44), (19, 13), (0, 25),
(19, 42), (1, 50), (44, 21), (6, 52), (1, 44), (7, 39), (29, 19),
(2, 23), (14, 23), (41, 35), (15, 38), (19, 6), (51, 4), (0, 32),
(36, 53), (48, 53), (41, 6), (47, 41), (29, 49), (35, 52), (22, 8),
(9, 31), (51, 37), (26, 10), (1, 25), (35, 23), (2, 45), (0, 49),
(50, 21), (43, 20), (16, 3), (15, 39), (47, 34), (49, 42), (51, 18),
(5, 32), (26, 20), (37, 31), (45, 27), (22, 16), (12, 21), (43, 10),
(24, 3), (41, 26), (22, 44), (13, 52), (29, 50), (30, 23), (18, 10),
(5, 49), (29, 12), (24, 4), (43, 39), (46, 10), (17, 28), (34, 3),
(38, 27), (16, 21), (45, 40), (1, 11), (22, 28), (46, 39), (51, 46),
]
_sycamore_coupling_graph = CouplingGraph(_edges)
SycamoreModel = MachineModel(54, _sycamore_coupling_graph, google_gate_set)

# Sycamore23 Device
_qubits = cirq_google.Sycamore23.metadata.qubit_set
_qubit_map = {q: i for i, q in enumerate(list(_qubits))}
_pairs = cirq_google.Sycamore23.metadata.qubit_pairs
_edges = [(_qubit_map[q1], _qubit_map[q2]) for q1, q2 in _pairs]
_edges = [
(20, 3), (18, 12), (8, 12), (4, 18), (14, 8), (6, 2), (15, 2),
(20, 7), (21, 9), (4, 19), (0, 16), (14, 18), (13, 10), (20, 17),
(21, 18), (7, 2), (16, 22), (16, 12), (5, 2), (14, 9), (1, 19),
(17, 9), (14, 10), (15, 9), (8, 22), (5, 10), (0, 19), (12, 19),
(16, 11), (13, 8), (15, 10), (20, 15),
]
_sycamore23_coupling_graph = CouplingGraph(_edges)
Sycamore23Model = MachineModel(23, _sycamore23_coupling_graph, google_gate_set)

Expand Down
23 changes: 21 additions & 2 deletions bqskit/ext/cirq/translate.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,38 @@
"""This module implements functions for translating to and from Cirq."""
from __future__ import annotations

import cirq
from cirq.contrib.qasm_import import circuit_from_qasm
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import cirq

from bqskit.ir.circuit import Circuit
from bqskit.ir.lang.qasm2 import OPENQASM2Language


def cirq_to_bqskit(cc: cirq.Circuit) -> Circuit:
"""Convert Cirq's Circuit `cc` to a BQSKit Circuit."""
try:
import cirq
except ImportError as e:
raise ImportError(
'\n\nUnable to import cirq package.\n'
'Please ensure that it is installed with the following command:\n'
'\tpip install cirq\n',
) from e

circuit = OPENQASM2Language().decode(cirq.qasm(cc))
return circuit


def bqskit_to_cirq(circuit: Circuit) -> cirq.Circuit:
"""Convert a BQSKit Circuit to Cirq's Circuit."""
try:
from cirq.contrib.qasm_import import circuit_from_qasm
except ImportError as e:
raise ImportError(
'\n\nUnable to import cirq package.\n'
'Please ensure that it is installed with the following command:\n'
'\tpip install cirq\n',
) from e

return circuit_from_qasm(OPENQASM2Language().encode(circuit))
24 changes: 21 additions & 3 deletions bqskit/ext/pytket/translate.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
"""This module implements functions for translating to and from PyTKet."""
from __future__ import annotations

import pytket
from pytket.qasm import circuit_from_qasm_str
from pytket.qasm import circuit_to_qasm_str
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import pytket

from bqskit.ir.circuit import Circuit
from bqskit.ir.lang.qasm2 import OPENQASM2Language


def pytket_to_bqskit(qc: pytket.Circuit) -> Circuit:
"""Convert PyTKet's Circuit `cc` to a BQSKit Circuit."""
try:
from pytket.qasm import circuit_to_qasm_str
except ImportError as e:
raise ImportError(
'\n\nUnable to import pytket package.\n'
'Please ensure that it is installed with the following command:\n'
'\tpip install pytket\n',
) from e

circuit = OPENQASM2Language().decode(circuit_to_qasm_str(qc))
return circuit


def bqskit_to_pytket(circuit: Circuit) -> pytket.Circuit:
"""Convert a BQSKit Circuit to a PyTKet Circuit."""
try:
from pytket.qasm import circuit_from_qasm_str
except ImportError as e:
raise ImportError(
'\n\nUnable to import pytket package.\n'
'Please ensure that it is installed with the following command:\n'
'\tpip install pytket\n',
) from e

return circuit_from_qasm_str(OPENQASM2Language().encode(circuit))
4 changes: 3 additions & 1 deletion bqskit/ext/qiskit/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""This module implements functions for working with IBM Backends."""
from __future__ import annotations

from qiskit.providers import BackendV1
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from qiskit.providers import BackendV1

from bqskit.compiler import MachineModel
from bqskit.ir.gate import Gate
Expand Down
13 changes: 12 additions & 1 deletion bqskit/ext/qiskit/translate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""This module implements functions for translating to and from Qiskit."""
from __future__ import annotations

from qiskit import QuantumCircuit
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from qiskit import QuantumCircuit

from bqskit.ir.circuit import Circuit
from bqskit.ir.lang.qasm2 import OPENQASM2Language
Expand All @@ -17,6 +19,15 @@ def qiskit_to_bqskit(qc: QuantumCircuit) -> Circuit:

def bqskit_to_qiskit(circuit: Circuit) -> QuantumCircuit:
"""Convert a BQSKit Circuit to Qiskit's QuantumCircuit."""
try:
from qiskit import QuantumCircuit
except ImportError as e:
raise ImportError(
'\n\nUnable to import qiskit package.\n'
'Please ensure that it is installed with the following command:\n'
'\tpip install qiskit\n',
) from e

# circuit.renumber_qudits(list(reversed(range(circuit.num_qudits))))
return QuantumCircuit.from_qasm_str(OPENQASM2Language().encode(circuit))
# TODO: support gates not captured by qasm
24 changes: 21 additions & 3 deletions bqskit/ext/qutip/translate.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
"""This module implements functions for translating to and from QuTiP."""
from __future__ import annotations

from qutip import QubitCircuit
from qutip.qip.qasm import circuit_to_qasm_str
from qutip.qip.qasm import read_qasm
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from qutip import QubitCircuit

from bqskit.ir.circuit import Circuit
from bqskit.ir.lang.qasm2 import OPENQASM2Language


def qutip_to_bqskit(qc: QubitCircuit) -> Circuit:
"""Convert QuTiP's QubitCircuit `qc` to a BQSKit Circuit."""
try:
from qutip.qip.qasm import circuit_to_qasm_str
except ImportError as e:
raise ImportError(
'\n\nUnable to import qutip package.\n'
'Please ensure that it is installed with the following command:\n'
'\tpip install qutip\n',
) from e

circuit = OPENQASM2Language().decode(circuit_to_qasm_str(qc))
return circuit


def bqskit_to_qutip(circuit: Circuit) -> QubitCircuit:
"""Convert a BQSKit Circuit to QuTiP's QubitCircuit."""
try:
from qutip.qip.qasm import read_qasm
except ImportError as e:
raise ImportError(
'\n\nUnable to import qutip package.\n'
'Please ensure that it is installed with the following command:\n'
'\tpip install qutip\n',
) from e

return read_qasm(OPENQASM2Language().encode(circuit), strmode=True)
2 changes: 1 addition & 1 deletion bqskit/ir/gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
from typing import TYPE_CHECKING

from bqskit.ir.location import CircuitLocation
from bqskit.qis.unitary.unitary import RealVector
from bqskit.qis.unitary.unitary import Unitary

if TYPE_CHECKING:
from bqskit.qis.unitary.unitary import RealVector
from bqskit.ir.gates.composed.frozenparam import FrozenParameterGate


Expand Down
58 changes: 43 additions & 15 deletions bqskit/ir/gates/constant/swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
from __future__ import annotations

from bqskit.ir.gates.constantgate import ConstantGate
from bqskit.ir.gates.qubitgate import QubitGate
from bqskit.qis.unitary.unitarymatrix import UnitaryMatrix
from bqskit.qis.permutation import PermutationMatrix
from bqskit.utils.typing import is_integer


class SwapGate(ConstantGate, QubitGate):
class SwapGate(ConstantGate):
"""
The two-qubit swap gate.
The two-qudit swap gate.
The swap gate is given by the following unitary:
This gate swaps the state of two qudits. For example, The qubit swap
gate is given by the following unitary:
.. math::
Expand All @@ -22,13 +23,40 @@ class SwapGate(ConstantGate, QubitGate):
\\end{pmatrix}
"""

_num_qudits = 2
_qasm_name = 'swap'
_utry = UnitaryMatrix(
[
[1, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 1],
],
)
def __init__(self, radix: int = 2) -> None:
"""
Create a swap gate, defaulting to the qubit swap gate.
Args:
radix (int): The base of the qudits being swapped.
Defaults to qubits or base 2. (Default: 2)
Raises:
ValueError: If radix is less than two.
"""
if not is_integer(radix):
raise TypeError('Expected a single integer radix.')

if radix < 2:
raise ValueError('Radix must be at least 2.')

self._num_qudits = 2
self._radixes = (radix, radix)
self._dim = radix * radix
self._utry = PermutationMatrix.gen_swap_unitary(radix)
self._qasm_name = 'swap'

def __eq__(self, other: object) -> bool:
return (
isinstance(other, SwapGate)
and self.radixes == other.radixes
)

def __hash__(self) -> int:
return hash(('swapgate', self.radixes[0]))

def __str__(self) -> str:
if self.is_qubit_only():
return 'SwapGate'
else:
return f'SwapGate({self.radixes[0]})'
Loading

0 comments on commit 5d46cda

Please sign in to comment.