Skip to content

Commit

Permalink
Improve circuit compilation performance (#375)
Browse files Browse the repository at this point in the history
  • Loading branch information
ohuettenhofer authored Nov 30, 2024
1 parent 4dbee52 commit a12e33f
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 16 deletions.
35 changes: 20 additions & 15 deletions src/tequila/circuit/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from .qpic import export_to


class QCircuit():
"""
Fundamental class representing an abstract circuit.
Expand Down Expand Up @@ -254,8 +255,8 @@ def replace_gates(self, positions: list, circuits: list, replace: list = None):
the gates to add at the corresponding positions
replace: list of bool: (Default value: None)
Default is None which corresponds to all true
decide if gates shall be replaces or if the new parts shall be inserted without replacement
if replace[i] = true: gate at position [i] will be replaces by gates[i]
decide if gates shall be replaced or if the new parts shall be inserted without replacement
if replace[i] = true: gate at position [i] will be replaced by gates[i]
if replace[i] = false: gates[i] circuit will be inserted at position [i] (beaming before gate previously at position [i])
Returns
-------
Expand All @@ -271,8 +272,9 @@ def replace_gates(self, positions: list, circuits: list, replace: list = None):
dataset = zip(positions, circuits, replace)
dataset = sorted(dataset, key=lambda x: x[0])

offset = 0
new_gatelist = self.gates
new_gatelist = []
last_idx = -1

for idx, circuit, do_replace in dataset:

# failsafe
Expand All @@ -283,13 +285,14 @@ def replace_gates(self, positions: list, circuits: list, replace: list = None):
else:
gatelist = [circuit]

pos = idx + offset
if do_replace:
new_gatelist = new_gatelist[:pos] + gatelist + new_gatelist[pos + 1:]
offset += len(gatelist) - 1
else:
new_gatelist = new_gatelist[:pos] + gatelist + new_gatelist[pos:]
offset += len(gatelist)
new_gatelist += self.gates[last_idx + 1:idx]
new_gatelist += gatelist
if not do_replace:
new_gatelist.append(self.gates[idx])

last_idx = idx

new_gatelist += self.gates[last_idx + 1:]

result = QCircuit(gates=new_gatelist)
result.n_qubits = max(result.n_qubits, self.n_qubits)
Expand Down Expand Up @@ -386,7 +389,7 @@ def __iadd__(self, other):
for k, v in other._parameter_map.items():
self._parameter_map[k] += [(x[0] + offset, x[1]) for x in v]

self._gates += copy.deepcopy(other.gates)
self._gates += other.gates
self._min_n_qubits = max(self._min_n_qubits, other._min_n_qubits)

return self
Expand Down Expand Up @@ -593,7 +596,7 @@ def _inpl_control_circ(self, control) -> None:
This is an in-place method, so it mutates self and doesn't return any value.
Raise TequilaWarning if there any qubits in common between self and control.
Raise TequilaWarning if there are any qubits in common between self and control.
"""
gates = self.gates
control = list_assignment(control)
Expand All @@ -610,8 +613,10 @@ def _inpl_control_circ(self, control) -> None:
if len(control_lst) < len(gate.control) + len(control):
# warnings.warn("Some of the controls {} were already included in the control "
# "of a gate {}.".format(control, gate), TequilaWarning)
raise TequilaWarning(f'Some of the controls {control} were already included '
f'in the control of a gate {gate}.')
raise TequilaWarning(f"Some of the controls {control} were already included "
f"in the control of a gate {gate}. "
f"This might be because the same instance of a gate is used in multiple places, "
f"e.g. because the same circuit was appended twice.")
else:
control_lst, not_control = list(control), list()

Expand Down
6 changes: 6 additions & 0 deletions src/tequila/utils/bitstrings.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ def integer(self, other: int):
self.update_nbits()
return self

def to_integer(self, numbering: BitNumbering):
if numbering == self.numbering:
return self.integer
else:
return reverse_int_bits(self.integer, self.nbits)

@property
def array(self):
return [int(i) for i in self.binary]
Expand Down
2 changes: 1 addition & 1 deletion src/tequila/wavefunction/qubit_wavefunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def normalize(self, inplace: bool = False) -> QubitWaveFunction:
# because the __mul__ implementation of the number tries to perform some sort of array
# operation.
def length(self):
return sum(1 for _ in self.raw_items())
return sum(1 for (k, v) in self.raw_items() if abs(v) > 1e-6)

def __repr__(self):
result = str()
Expand Down

0 comments on commit a12e33f

Please sign in to comment.