Skip to content

Commit 5cc87eb

Browse files
authored
Merge pull request #55 from BQSKit/dev
0.4.0
2 parents 8471f28 + 9f3eff1 commit 5cc87eb

File tree

106 files changed

+2631
-956
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+2631
-956
lines changed

.github/workflows/pre-commit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- uses: actions/checkout@v1
1313
- uses: actions/setup-python@v1
1414
with:
15-
python-version: '3.9'
15+
python-version: '3.10'
1616
- name: set PY
1717
run: echo "name=PY::$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" >> $GITHUB_ENV
1818
- uses: actions/cache@v1

.github/workflows/tox.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
tox:
1010
strategy:
1111
matrix:
12-
python-version: ['3.7', '3.8', '3.9']
12+
python-version: ['3.7', '3.8', '3.9', '3.10']
1313
os: [macOS-latest, windows-latest, ubuntu-latest]
1414

1515
runs-on: ${{ matrix.os }}

.pre-commit-config.yaml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.0.1
3+
rev: v4.1.0
44
hooks:
55
- id: trailing-whitespace
66
- id: end-of-file-fixer
@@ -30,36 +30,36 @@ repos:
3030
- --wrap-summaries=80
3131
- --wrap-descriptions=80
3232
- repo: https://github.com/pre-commit/mirrors-autopep8
33-
rev: v1.5.7
33+
rev: v1.6.0
3434
hooks:
3535
- id: autopep8
3636
args:
3737
- --in-place
3838
- -a
3939
- --max-line-length=80
4040
- repo: https://github.com/asottile/pyupgrade
41-
rev: v2.29.0
41+
rev: v2.31.0
4242
hooks:
4343
- id: pyupgrade
4444
args:
4545
- --py36-plus
4646
- --keep-percent-format
4747
- repo: https://github.com/asottile/reorder_python_imports
48-
rev: v2.6.0
48+
rev: v2.7.1
4949
hooks:
5050
- id: reorder-python-imports
5151
args:
5252
- --add-import
5353
- from __future__ import annotations
5454
- --py3-plus
5555
- repo: https://github.com/asottile/add-trailing-comma
56-
rev: v2.1.0
56+
rev: v2.2.1
5757
hooks:
5858
- id: add-trailing-comma
5959
args:
6060
- --py36-plus
6161
- repo: https://github.com/asottile/setup-cfg-fmt
62-
rev: v1.18.0
62+
rev: v1.20.0
6363
hooks:
6464
- id: setup-cfg-fmt
6565
- repo: https://github.com/myint/autoflake
@@ -68,11 +68,11 @@ repos:
6868
- id: autoflake
6969
args:
7070
- --in-place
71-
- repo: https://github.com/pre-commit/mirrors-mypy
72-
rev: v0.910-1
73-
hooks:
74-
- id: mypy
75-
additional_dependencies: ["numpy>=1.20,<1.21"]
71+
# - repo: https://github.com/pre-commit/mirrors-mypy
72+
# rev: v0.931
73+
# hooks:
74+
# - id: mypy
75+
# additional_dependencies: ["numpy>=1.21"]
7676
- repo: https://gitlab.com/pycqa/flake8
7777
rev: 3.9.2
7878
hooks:

bqskit/compiler/compiler.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
3838
All arguments are passed directly to Dask. You can use
3939
these to connect to and configure a Dask cluster.
4040
"""
41+
if 'silence_logs' not in kwargs:
42+
kwargs['silence_logs'] = logging.getLogger('bqskit').level
43+
4144
self.client = Client(*args, **kwargs)
4245
self.tasks: dict[uuid.UUID, Future] = {}
4346
_logger.info('Started compiler process.')
@@ -60,12 +63,12 @@ def close(self) -> None:
6063
self.client.close()
6164
self.tasks = {}
6265
_logger.info('Stopped compiler process.')
63-
except AttributeError:
66+
except (AttributeError, TypeError):
6467
pass
6568

6669
def submit(self, task: CompilationTask) -> None:
6770
"""Submit a CompilationTask to the Compiler."""
68-
executor = Executor(task)
71+
executor = self.client.scatter(Executor(task))
6972
future = self.client.submit(Executor.run, executor, pure=False)
7073
self.tasks[task.task_id] = future
7174
_logger.info('Submitted task: %s' % task.task_id)
@@ -76,7 +79,7 @@ def status(self, task: CompilationTask) -> str:
7679

7780
def result(self, task: CompilationTask) -> Circuit:
7881
"""Block until the CompilationTask is finished, return its result."""
79-
circ = self.tasks[task.task_id].result()
82+
circ = self.tasks[task.task_id].result()[0]
8083
return circ
8184

8285
def cancel(self, task: CompilationTask) -> None:
@@ -90,3 +93,9 @@ def compile(self, task: CompilationTask) -> Circuit:
9093
self.submit(task)
9194
result = self.result(task)
9295
return result
96+
97+
def analyze(self, task: CompilationTask, key: str) -> Any:
98+
"""Gather the value associated with `key` in the task's data."""
99+
if task.task_id not in self.tasks:
100+
self.submit(task)
101+
return self.tasks[task.task_id].result()[1][key]

bqskit/compiler/executor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ def __init__(self, task: CompilationTask) -> None:
3131
self.data: dict[str, Any] = {'executor': self}
3232
self.done = False
3333

34-
def run(self) -> Circuit:
34+
def run(self) -> tuple[Circuit, dict[str, Any]]:
3535
"""Execute the task."""
3636
with threadpool_limits(limits=1):
3737
for pass_obj in self.passes:
3838
pass_obj.run(self.circuit, self.data)
3939
self.done = True
40-
return self.circuit
40+
return self.circuit, self.data

bqskit/compiler/machine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def get_locations(self, block_size: int) -> list[CircuitLocation]:
9494
)
9595

9696
if block_size <= 0:
97-
raise ValueError('Nonpositive block_size; got {block_size}.')
97+
raise ValueError(f'Nonpositive block_size; got {block_size}.')
9898

9999
locations: set[CircuitLocation] = set()
100100

bqskit/compiler/task.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@
77

88
from bqskit.compiler.basepass import BasePass
99
from bqskit.ir.circuit import Circuit
10-
from bqskit.ir.gates.constant.cx import CNOTGate
10+
from bqskit.ir.gates import CircuitGate
11+
from bqskit.ir.gates import CNOTGate
12+
from bqskit.ir.operation import Operation
1113
from bqskit.passes.control import ForEachBlockPass
1214
from bqskit.passes.control.predicates.count import GateCountPredicate
1315
from bqskit.passes.control.whileloop import WhileLoopPass
1416
from bqskit.passes.partitioning.cluster import ClusteringPartitioner
1517
from bqskit.passes.partitioning.quick import QuickPartitioner
1618
from bqskit.passes.processing import ScanningGateRemovalPass
17-
from bqskit.passes.processing import WindowOptimizationPass
1819
from bqskit.passes.synthesis import QFASTDecompositionPass
19-
from bqskit.passes.synthesis.leap import OptimizedLEAPPass
20+
from bqskit.passes.synthesis.leap import LEAPSynthesisPass
2021
from bqskit.passes.util import UnfoldPass
2122
from bqskit.qis.unitary.unitarymatrix import UnitaryLike
2223

@@ -57,15 +58,19 @@ def synthesize(utry: UnitaryLike) -> CompilationTask:
5758
_logger.warning('Synthesis input size is very large.')
5859

5960
inner_seq = [
60-
OptimizedLEAPPass(),
61-
WindowOptimizationPass(),
61+
LEAPSynthesisPass(),
6262
ScanningGateRemovalPass(),
6363
]
6464

6565
passes: list[BasePass] = []
6666
if num_qudits >= 5:
6767
passes.append(QFASTDecompositionPass())
68-
passes.append(ForEachBlockPass(inner_seq))
68+
passes.append(
69+
ForEachBlockPass(
70+
inner_seq,
71+
replace_filter=less_2q_gates,
72+
),
73+
)
6974
passes.append(UnfoldPass())
7075
else:
7176
passes.extend(inner_seq)
@@ -81,23 +86,32 @@ def optimize(circuit: Circuit) -> CompilationTask:
8186
return CompilationTask.synthesize(circuit.get_unitary())
8287

8388
inner_seq = [
84-
OptimizedLEAPPass(),
89+
LEAPSynthesisPass(),
8590
ScanningGateRemovalPass(),
8691
]
8792

8893
passes: list[BasePass] = []
8994
passes.append(QuickPartitioner(3))
90-
passes.append(ForEachBlockPass(inner_seq))
95+
passes.append(ForEachBlockPass(inner_seq, replace_filter=less_2q_gates))
9196
passes.append(UnfoldPass())
9297

9398
iterative_reopt = WhileLoopPass(
9499
GateCountPredicate(CNOTGate()),
95100
[
96101
ClusteringPartitioner(3, 4),
97-
ForEachBlockPass(inner_seq),
102+
ForEachBlockPass(inner_seq, replace_filter=less_2q_gates),
98103
UnfoldPass(),
99104
],
100105
)
101106

102107
passes.append(iterative_reopt)
103108
return CompilationTask(circuit, passes)
109+
110+
111+
def less_2q_gates(circuit: Circuit, op: Operation) -> bool:
112+
"""Replace `circuit' with `op` if has less 2 qubit gates."""
113+
if not isinstance(op, CircuitGate):
114+
return True
115+
og_num_2q_gate = len([op for op in op._circuit if op.num_qudits >= 2])
116+
new_num_2q_gate = len([op for op in circuit if op.num_qudits >= 2])
117+
return new_num_2q_gate > og_num_2q_gate

bqskit/exec/__init__.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
=============================================================
3+
Circuit Execution Module (:mod:`bqskit.exec`)
4+
=============================================================
5+
6+
.. currentmodule:: bqskit.exec
7+
8+
BQSKit supports a variety of ways to execute circuits through
9+
CircuitRunner.
10+
11+
.. rubric:: Core Classes
12+
13+
.. autosummary::
14+
:toctree: autogen
15+
:recursive:
16+
17+
CircuitRunner
18+
RunnerResults
19+
20+
.. rubric:: CircuitRunners
21+
22+
.. autosummary::
23+
:toctree: autogen
24+
:recursive:
25+
26+
QuestRunner
27+
IBMQRunner
28+
SimulationRunner
29+
"""
30+
from __future__ import annotations
31+
32+
__all__ = [
33+
'CircuitRunner',
34+
'RunnerResults',
35+
'QuestRunner',
36+
'SimulationRunner',
37+
]
38+
39+
from bqskit.exec.results import RunnerResults
40+
from bqskit.exec.runner import CircuitRunner
41+
try:
42+
from bqskit.exec.runners.ibmq import IBMQRunner
43+
__all__ += ['IBMQRunner']
44+
except ImportError:
45+
pass
46+
from bqskit.exec.runners.quest import QuestRunner
47+
from bqskit.exec.runners.sim import SimulationRunner

bqskit/exec/results.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from __future__ import annotations
2+
3+
from typing import Sequence
4+
5+
import numpy as np
6+
import numpy.typing as npt
7+
8+
9+
class RunnerResults:
10+
"""The result of running a Circuit through a CircuitRunner."""
11+
12+
def __init__(
13+
self,
14+
num_qudits: int,
15+
radixes: Sequence[int],
16+
probs: Sequence[float],
17+
) -> None:
18+
"""Construct a RunnerResults object."""
19+
self.num_qudits = num_qudits
20+
self.radixes = radixes
21+
self.probs = np.array(probs)
22+
23+
def get_counts(self, shots: int) -> npt.NDArray[np.int64]:
24+
return np.asarray(np.multiply(shots, self.probs), np.int64)
25+
26+
def __str__(self) -> str:
27+
pass

bqskit/exec/runner.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from __future__ import annotations
2+
3+
from abc import ABC
4+
from abc import abstractmethod
5+
6+
from bqskit.exec.results import RunnerResults
7+
from bqskit.ir.circuit import Circuit
8+
9+
10+
class CircuitRunner(ABC):
11+
"""A CircuitRunner is responsible for executing a quantum circuit."""
12+
13+
@abstractmethod
14+
def run(self, circuit: Circuit) -> RunnerResults:
15+
"""
16+
Execute the circuit and return results.
17+
18+
Args:
19+
circuit (Circuit): The circuit to run.
20+
21+
Returns:
22+
(RunnerResults): The results from executing this circuit.
23+
"""

0 commit comments

Comments
 (0)