Skip to content

Commit 4e62a6c

Browse files
authored
Merge pull request #101 from BQSKit/1.0.2
1.0.2
2 parents a4197c1 + 3565054 commit 4e62a6c

19 files changed

Lines changed: 179952 additions & 75 deletions

File tree

.github/workflows/tox.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ jobs:
2121
- name: install tox
2222
run: python -m pip install --upgrade tox virtualenv setuptools pip
2323
- name: run tox
24+
env:
25+
NUMBER_RANDOM_CIRCUITS: 100
2426
run: tox -e py

bqskit/ext/rigetti.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555

5656
_horizontal_connections = [
5757
[
58-
(i + 1, j + 7),
59-
(i + 2, j + 6),
58+
(i + 1, j + 6),
59+
(i + 2, j + 5),
6060
]
6161
for i, j in [(8 * r, 8 * (r + 1)) for r in [0, 1, 2, 3, 5, 6, 7, 8]]
6262
]

bqskit/ir/circuit.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,11 @@ def pop_cycle(self, cycle_index: int) -> None:
655655
for point in points:
656656
self.pop(point)
657657
return
658-
else:
659-
self._circuit.pop(cycle_index)
658+
659+
self._circuit.pop(cycle_index)
660+
661+
if cycle_index == -1 or cycle_index == self.num_cycles:
662+
return
660663

661664
dec_point = lambda p: CircuitPoint(p.cycle - 1, p.qudit)
662665
shift_point = lambda p: p if p.cycle < cycle_index else dec_point(p)

bqskit/passes/mapping/setmodel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(self, model: MachineModel) -> None:
3030
def run(self, circuit: Circuit, data: dict[str, Any] = {}) -> None:
3131
"""Perform the pass's operation, see :class:`BasePass` for more."""
3232
if 'machine_model' in data:
33-
_logger.warning('Overriding existing machine model.')
33+
_logger.info('Overriding existing machine model.')
3434

3535
if self.model.num_qudits < circuit.num_qudits:
3636
raise RuntimeError('Machine model is too small for circuit.')

bqskit/passes/partitioning/quick.py

Lines changed: 72 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ def run(self, circuit: Circuit, data: dict[str, Any] = {}) -> None:
7878
active_bins: list[Bin | None] = [
7979
None for _ in range(circuit.num_qudits)
8080
]
81+
8182
# Tracks the first cycle in circuit not included in partitioned_circuit
8283
dividing_line: dict[int, int] = {
8384
i: 0 if circuit._front[i] is None else circuit._front[i].cycle # type: ignore # noqa
@@ -134,7 +135,7 @@ def process_pending_bins() -> None:
134135
if all(q in loc for q in qudits):
135136
prev_op = partitioned_circuit.pop(p)
136137
pg = cast(CircuitGate, prev_op.gate)
137-
prev_circ = pg._circuit
138+
prev_circ = pg._circuit.copy()
138139
local_loc = [loc.index(q) for q in qudits]
139140
subc.insert_circuit(0, prev_circ, local_loc)
140141

@@ -146,7 +147,7 @@ def process_pending_bins() -> None:
146147
if all(q in qudits for q in loc):
147148
prev_op = partitioned_circuit.pop(p)
148149
pg = cast(CircuitGate, prev_op.gate)
149-
prev_circ = pg._circuit
150+
prev_circ = pg._circuit.copy()
150151
lloc = [qudits.index(q) for q in loc]
151152
prev_circ.append_circuit(subc, lloc)
152153
subc.become(prev_circ)
@@ -166,6 +167,7 @@ def process_pending_bins() -> None:
166167
for qudit in bin.qudits:
167168
dividing_line[qudit] = bin.ends[qudit] + 1 # type: ignore # noqa
168169
need_to_reprocess = True
170+
break
169171

170172
for bin in to_remove:
171173
pending_bins.remove(bin)
@@ -175,16 +177,16 @@ def process_pending_bins() -> None:
175177
point = CircuitPoint(cycle, op.location[0])
176178
location = op.location
177179

178-
# Get all currently active bins that share atleast one qudit
180+
# Get all currently active bins that share at least one qudit
179181
overlapping_bins: list[Bin] = list({
180182
active_bins[q] for q in location # type: ignore
181183
if active_bins[q] is not None
182184
})
183185

184186
# Get all the currently active bins that can have op added to them
185187
admissible_bins = [
186-
b for b in overlapping_bins
187-
if b.can_accommodate(location, self.block_size)
188+
bin for bin in overlapping_bins
189+
if bin.can_accommodate(location, self.block_size)
188190
]
189191

190192
# Close location on inadmissible overlapping bins
@@ -193,57 +195,50 @@ def process_pending_bins() -> None:
193195
if close_bin_qudits(bin, location, cycle):
194196
num_closed += 1
195197

196-
# If we cannot add this op to any bin, make a new one
198+
# Select bin or make new one
197199
if len(admissible_bins) == 0:
200+
# If we cannot add this op to any bin, make a new one
198201
assert all(active_bins[q] is None for q in location)
199-
new_bin = Bin(point, location)
200-
for q in location:
201-
active_bins[q] = new_bin
202-
203-
# Block qudits to prevent circular dependencies
204-
for bin in overlapping_bins:
205-
bin.blocked_qudits.update(new_bin.qudits)
206-
207-
for active_bin in active_bins:
208-
if active_bin is None or active_bin == bin:
209-
continue
210-
211-
indirect = active_bin.blocked_qudits
212-
indirect = indirect.intersection(bin.qudits)
213-
if len(indirect) != 0:
214-
active_bin.blocked_qudits.update(new_bin.qudits)
202+
selected_bin = Bin()
215203

216204
else:
217-
# Add to first admissible bin
218-
selected_bin = admissible_bins[0]
219-
220-
# Deactivate the rest
221-
for bin in admissible_bins[1:]:
222-
if close_bin_qudits(bin, location, cycle):
223-
num_closed += 1
224-
225-
# Add op to selected_bin
226-
selected_bin.add_op(point, location)
227-
for q in location:
228-
if active_bins[q] is None:
229-
active_bins[q] = selected_bin
230-
else:
231-
assert active_bins[q] == selected_bin
232-
233-
# Block qudits to prevent circular dependencies
234-
for bin in overlapping_bins:
235-
if bin == selected_bin:
236-
continue
237-
bin.blocked_qudits.update(selected_bin.qudits)
238-
239-
for active_bin in active_bins:
240-
if active_bin is None or active_bin == bin:
241-
continue
242-
243-
indirect = active_bin.blocked_qudits
244-
indirect = indirect.intersection(bin.qudits)
245-
if len(indirect) != 0:
246-
active_bin.blocked_qudits.update(new_bin.qudits)
205+
# Otherwise select an admissible bin
206+
found = False
207+
for bin in admissible_bins:
208+
if all(q in bin.qudits for q in location):
209+
selected_bin = bin
210+
found = True
211+
break
212+
213+
if not found:
214+
selected_bin = admissible_bins[0]
215+
216+
# Close the overlapping qudits on the other admissible bins
217+
for bin in admissible_bins:
218+
if bin != selected_bin:
219+
if close_bin_qudits(bin, location, cycle):
220+
num_closed += 1
221+
222+
# Add op to selected_bin
223+
selected_bin.add_op(point, location)
224+
for q in location:
225+
if active_bins[q] is None:
226+
active_bins[q] = selected_bin
227+
else:
228+
assert active_bins[q] == selected_bin
229+
230+
# Block qudits to prevent circular dependencies
231+
for active_bin in active_bins:
232+
if active_bin is None:
233+
continue
234+
if active_bin == selected_bin:
235+
continue
236+
237+
indirect = active_bin.blocked_qudits
238+
indirect = indirect.union(active_bin.qudits)
239+
indirect = indirect.intersection(selected_bin.qudits)
240+
if len(indirect) != 0:
241+
active_bin.blocked_qudits.update(selected_bin.qudits)
247242

248243
# If a new bin was finalized, reprocess pending bins
249244
if num_closed >= 5:
@@ -258,6 +253,13 @@ def process_pending_bins() -> None:
258253
# Process remaining bins
259254
process_pending_bins()
260255

256+
if len(pending_bins) != 0:
257+
raise RuntimeError(
258+
'Unable to process all pending bins during partitioning.\n'
259+
'This should never happen and is a major issue'
260+
', please make a bug report containing the input circuit.',
261+
)
262+
261263
# Become partitioned circuit
262264
circuit.become(partitioned_circuit, False)
263265

@@ -268,30 +270,26 @@ class Bin:
268270
id: int = 0
269271
"""Unique ID counter for Bin instances."""
270272

271-
def __init__(
272-
self,
273-
point: CircuitPoint,
274-
location: CircuitLocation,
275-
) -> None:
273+
def __init__(self) -> None:
276274
"""Can start a new bin from an operation."""
277275

278276
# The qudits in the bin
279-
self.qudits: list[int] = list(location)
277+
self.qudits: list[int] = []
280278

281279
# The starting cycles for each qudit (inclusive)
282-
self.starts: dict[int, int] = {q: point.cycle for q in location}
280+
self.starts: dict[int, int] = {}
283281

284282
# The ending cycles for each qudit (inclusive)
285-
self.ends: dict[int, int | None] = {q: None for q in location}
283+
self.ends: dict[int, int | None] = {}
286284

287285
# The qudits that can still accept new gates
288-
self.active_qudits: list[int] = list(location)
286+
self.active_qudits: list[int] = []
289287

290288
# Qudits that cannot be added to the bin
291289
self.blocked_qudits: set[int] = set()
292290

293291
# Points for each operation in this bin
294-
self.op_list: list[CircuitPoint] = [point]
292+
self.op_list: list[CircuitPoint] = []
295293

296294
self.id = Bin.id
297295
Bin.id += 1
@@ -302,11 +300,10 @@ def __hash__(self) -> int:
302300
def __eq__(self, other: object) -> bool:
303301
return isinstance(other, Bin) and self.id == other.id
304302

305-
def add_op(
306-
self,
307-
point: CircuitPoint,
308-
location: CircuitLocation,
309-
) -> None:
303+
def __repr__(self) -> str:
304+
return 'Bin ' + str(self.id)
305+
306+
def add_op(self, point: CircuitPoint, location: CircuitLocation) -> None:
310307
"""Add an operation the bin."""
311308
for q in location:
312309
if q not in self.qudits:
@@ -322,7 +319,11 @@ def can_accommodate(self, loc: CircuitLocation, block_size: int) -> bool:
322319
An op can be added to the bin if all overlapping qudits are active in
323320
the bin and if the new bin won't be too large.
324321
"""
325-
if any(q in loc for q in self.blocked_qudits):
322+
if any(
323+
q in self.blocked_qudits
324+
and q not in self.active_qudits
325+
for q in loc
326+
):
326327
return False
327328

328329
overlapping_qudits_are_active = all(
@@ -334,3 +335,6 @@ def can_accommodate(self, loc: CircuitLocation, block_size: int) -> bool:
334335
too_big = len(set(self.qudits + list(loc))) > size_limit
335336

336337
return overlapping_qudits_are_active and not too_big
338+
339+
340+
1

0 commit comments

Comments
 (0)