Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler Top-Down Integration #49

Merged
merged 41 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
000538e
removed test file of obsolete pass
KevinMTO Jun 6, 2024
5613167
Merge branch 'main' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Jun 6, 2024
98a356b
crot modification
KevinMTO Jun 10, 2024
e10633d
integration of two body compiler
KevinMTO Jun 21, 2024
eb765dc
Merge branch 'main' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Jun 21, 2024
1c6dfdd
integration of compiler
KevinMTO Jul 30, 2024
7dc2cd3
bug fix of matrix factory
KevinMTO Aug 15, 2024
184e04a
Merge branch 'main' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Aug 15, 2024
756c6d7
Merge branch 'main' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Aug 21, 2024
8a803b7
testing improved for full stack compiler and simulator
KevinMTO Aug 21, 2024
f22aa2b
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 21, 2024
c8cd19e
small codeql correction
KevinMTO Aug 22, 2024
250da67
fix to test and typing
KevinMTO Aug 22, 2024
94e6216
test fix state preparation
KevinMTO Aug 22, 2024
39bf138
merge
KevinMTO Aug 22, 2024
c11f390
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 22, 2024
ffea92b
fix interacting test
KevinMTO Aug 22, 2024
4c77ac3
Merge branch 'two_dit' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Aug 22, 2024
b996d38
change permutation of state
KevinMTO Aug 22, 2024
f3e8e08
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 22, 2024
09049ee
fix test
KevinMTO Aug 22, 2024
1290348
Merge branch 'two_dit' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Aug 22, 2024
c998585
removed test as test
KevinMTO Aug 22, 2024
cdc9362
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 22, 2024
0ab8f46
multiplicatino fix
KevinMTO Aug 22, 2024
17197c1
Merge branch 'two_dit' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Aug 22, 2024
15aab98
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 22, 2024
086e8e5
multiplicatino fix
KevinMTO Aug 22, 2024
f5eed92
multiplicatino fix
KevinMTO Aug 22, 2024
65baa1d
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 22, 2024
14e5955
update to workflow
KevinMTO Aug 22, 2024
10da2e6
update to workflow
KevinMTO Aug 22, 2024
5c0719e
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 22, 2024
46ce11f
overcome @= precommit change
KevinMTO Aug 22, 2024
077d613
overcome @= precommit change
KevinMTO Aug 22, 2024
12f245e
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 22, 2024
03d7fc1
fix toml
KevinMTO Aug 22, 2024
c7f881e
Merge branch 'two_dit' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Aug 22, 2024
9a393ed
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 22, 2024
75d2351
fix toml
KevinMTO Aug 22, 2024
670f4f2
Merge branch 'two_dit' of github.com:cda-tum/mqt-qudits into two_dit
KevinMTO Aug 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/mqt/qudits/compiler/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from .compiler_pass import CompilerPass
from .dit_manager import QuditCompiler
from .dit_compiler import QuditCompiler

__all__ = [
"CompilerPass",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ def gate_expand_to_circuit(gate, circuits_size, target, dims=None):
msg = "target must be integer < integer circuits_size"
raise ValueError(msg)

upper = [np.identity(dims[i], dtype="complex") for i in range(circuits_size - target - 1)]
upper = [np.identity(dims[i], dtype="complex") for i in range(target + 1, circuits_size)]
lower = [np.identity(dims[j], dtype="complex") for j in range(target)]
circ = [*upper, gate, *lower]
circ = [*lower, gate, *upper]
res = circ[-1]

for i in reversed(list(range(1, len(circ)))):
Expand Down
10 changes: 9 additions & 1 deletion src/mqt/qudits/compiler/compiler_pass.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from mqt.qudits.quantum_circuit import QuantumCircuit
from mqt.qudits.quantum_circuit.gate import Gate


class CompilerPass(ABC):
def __init__(self, backend, **kwargs) -> None:
self.backend = backend

def transpile_gate(self, gate: Gate) -> list[Gate]:

Check notice

Code scanning / CodeQL

Mismatch between signature and use of an overridden method Note

Overridden method signature does not match
call
, where it is passed too many arguments. Overriding method
method PhyLocAdaPass.transpile_gate
matches the call.
pass

@abstractmethod
def transpile(self, circuit):
def transpile(self, circuit: QuantumCircuit) -> QuantumCircuit:
pass
79 changes: 79 additions & 0 deletions src/mqt/qudits/compiler/dit_compiler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from __future__ import annotations

from ..core.lanes import Lanes
from ..quantum_circuit.components.extensions.gate_types import GateTypes
from .naive_local_resynth import NaiveLocResynthOptPass
from .onedit import LogLocQRPass, PhyLocAdaPass, PhyLocQRPass, ZPropagationOptPass, ZRemovalOptPass
from .twodit import LogEntQRCEXPass
from .twodit.entanglement_qr.phy_ent_qr_cex_decomp import PhyEntQRCEXPass


class QuditCompiler:
passes_enabled = {
"PhyLocQRPass": PhyLocQRPass,
"PhyLocAdaPass": PhyLocAdaPass,
"LocQRPass": PhyLocQRPass,
"LocAdaPass": PhyLocAdaPass,
"LogLocQRPass": LogLocQRPass,
"ZPropagationOptPass": ZPropagationOptPass,
"ZRemovalOptPass": ZRemovalOptPass,
"LogEntQRCEXPass": LogEntQRCEXPass,
"PhyEntQRCEXPass": PhyEntQRCEXPass,
"NaiveLocResynthOptPass": NaiveLocResynthOptPass,
}

def __init__(self) -> None:
pass

def compile(self, backend, circuit, passes_names):
passes_dict = {}
new_instr = []
# Instantiate and execute created classes
for compiler_pass in passes_names:
compiler_pass = self.passes_enabled[compiler_pass]
decomposition = compiler_pass(backend)
if "Loc" in str(compiler_pass):
passes_dict[GateTypes.SINGLE] = decomposition
elif "Ent" in str(compiler_pass):
passes_dict[GateTypes.TWO] = decomposition
elif "Multi" in str(compiler_pass):
passes_dict[GateTypes.MULTI] = decomposition
for gate in circuit.instructions:
decomposer = passes_dict.get(gate.gate_type)
new_instructions = decomposer.transpile_gate(gate)
new_instr.extend(new_instructions)

circuit.set_instructions(new_instr)
circuit.set_mapping([graph.log_phy_map for graph in backend.energy_level_graphs])

return circuit

def compile_O0(self, backend, circuit):
passes = ["PhyLocQRPass", "PhyEntQRCEXPass"]
compiled = self.compile(backend, circuit, passes)

mappings = []
for i, graph in enumerate(backend.energy_level_graphs):
mappings.append([lev for lev in graph.log_phy_map if lev < circuit.dimensions[i]])
compiled.set_mapping(mappings)
return compiled

def compile_O1(self, backend, circuit):
phyloc = PhyLocAdaPass(backend)
phyent = PhyEntQRCEXPass(backend)

lanes = Lanes(circuit)
new_instructions = []
for gate in circuit.instructions:
if gate.gate_type is GateTypes.SINGLE:
ins = phyloc.transpile_gate(gate, lanes.next_is_local(gate))
new_instructions.extend(ins)
else:
ins = phyent.transpile_gate(gate)
new_instructions.extend(ins)
transpiled_circuit = circuit.copy()
mappings = []
for i, graph in enumerate(backend.energy_level_graphs):
mappings.append([lev for lev in graph.log_phy_map if lev < circuit.dimensions[i]])
transpiled_circuit.set_mapping(mappings)
return transpiled_circuit.set_instructions(new_instructions)
26 changes: 0 additions & 26 deletions src/mqt/qudits/compiler/dit_manager.py

This file was deleted.

7 changes: 7 additions & 0 deletions src/mqt/qudits/compiler/naive_local_resynth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from __future__ import annotations

from mqt.qudits.compiler.naive_local_resynth.local_resynth import NaiveLocResynthOptPass

__all__ = [
"NaiveLocResynthOptPass",
]
46 changes: 46 additions & 0 deletions src/mqt/qudits/compiler/naive_local_resynth/local_resynth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from __future__ import annotations

from typing import NoReturn

import numpy as np

from mqt.qudits.compiler import CompilerPass
from mqt.qudits.core.lanes import Lanes
from mqt.qudits.quantum_circuit.components.extensions.gate_types import GateTypes
from mqt.qudits.quantum_circuit.gates import CustomOne


class NaiveLocResynthOptPass(CompilerPass):
def __init__(self, backend) -> None:
super().__init__(backend)

def transpile_gate(self, gate) -> NoReturn:
raise NotImplementedError

def transpile(self, circuit):
self.circuit = circuit
self.lanes = Lanes(self.circuit)

for line in sorted(self.lanes.index_dict.keys()):
grouped_line = self.lanes.find_consecutive_singles(self.lanes.index_dict[line])
new_line = []
for group in grouped_line[line]:
if group[0][1].gate_type == GateTypes.SINGLE:
matrix = np.identity(self.circuit.dimensions[line])
for gate_tuple in group:
gate = gate_tuple[1]
gm = gate.to_matrix()
matrix = gm @ matrix
new_line.append((
group[0][0],
CustomOne(self.circuit, "CUm", line, matrix, self.circuit.dimensions[line]),
))
else:
new_line.append(group[0])

self.lanes.index_dict[line] = new_line

new_instructions = self.lanes.extract_instructions()

transpiled_circuit = self.circuit.copy()
return transpiled_circuit.set_instructions(new_instructions)
6 changes: 3 additions & 3 deletions src/mqt/qudits/compiler/onedit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from .local_phases_transpilation import ZPropagationPass, ZRemovalPass
from .local_phases_transpilation import ZPropagationOptPass, ZRemovalOptPass
from .mapping_aware_transpilation import PhyLocAdaPass, PhyLocQRPass
from .mapping_un_aware_transpilation import LogLocAdaPass, LogLocQRPass

Expand All @@ -9,6 +9,6 @@
"LogLocQRPass",
"PhyLocAdaPass",
"PhyLocQRPass",
"ZPropagationPass",
"ZRemovalPass",
"ZPropagationOptPass",
"ZRemovalOptPass",
]
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from __future__ import annotations

from .propagate_virtrz import ZPropagationPass
from .remove_phase_rotations import ZRemovalPass
from .propagate_virtrz import ZPropagationOptPass
from .remove_phase_rotations import ZRemovalOptPass

__all__ = [
"ZPropagationPass",
"ZRemovalPass",
"ZPropagationOptPass",
"ZRemovalOptPass",
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
from ...compilation_minitools import pi_mod


class ZPropagationPass(CompilerPass):
class ZPropagationOptPass(CompilerPass):
def __init__(self, backend, back=True) -> None:
super().__init__(backend)
self.back = back

def transpile_gate(self, gate):
return gate

def transpile(self, circuit):
return self.remove_z(circuit, self.back)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
from ... import CompilerPass


class ZRemovalPass(CompilerPass):
class ZRemovalOptPass(CompilerPass):
def __init__(self, backend) -> None:
super().__init__(backend)

def transpile_gate(self, gate):
return gate

def transpile(self, circuit):
circuit = self.remove_initial_rz(circuit)
return self.remove_trailing_rz_sequence(circuit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,61 +25,33 @@ class PhyLocAdaPass(CompilerPass):
def __init__(self, backend) -> None:
super().__init__(backend)

def transpile_gate(self, gate, vrz_prop=False):
energy_graph_i = self.backend.energy_level_graphs[gate._target_qudits]

QR = PhyQrDecomp(gate, energy_graph_i)

_decomp, algorithmic_cost, total_cost = QR.execute()

Adaptive = PhyAdaptiveDecomposition(
gate, energy_graph_i, (algorithmic_cost, total_cost), gate._dimensions, Z_prop=vrz_prop
)
(matrices_decomposed, _best_cost, new_energy_level_graph) = Adaptive.execute()

self.backend.energy_level_graphs[gate._target_qudits] = new_energy_level_graph
return [op.dag() for op in reversed(matrices_decomposed)]

def transpile(self, circuit):
self.circuit = circuit
instructions = circuit.instructions
new_instructions = []

for gate in instructions:
if gate.gate_type == GateTypes.SINGLE:
energy_graph_i = self.backend.energy_level_graphs[gate._target_qudits]
# ini_lpmap = list(self.backend.energy_level_graphs.log_phy_map)

# if self.verify:
# recover_dict = {}
# inode = self.energy_level_graph._1stInode
# if 'phase_storage' in self.energy_level_graph.nodes[inode]:
# for i in range(len(list(self.energy_level_graph.nodes))):
# thetaZ = newMod(self.energy_level_graph.nodes[i]['phase_storage'])
# recover_dict[i] = thetaZ

QR = PhyQrDecomp(gate, energy_graph_i)

_decomp, algorithmic_cost, total_cost = QR.execute()

Adaptive = PhyAdaptiveDecomposition(
gate, energy_graph_i, (algorithmic_cost, total_cost), gate._dimensions
)

(
matrices_decomposed,
_best_cost,
self.backend.energy_level_graphs[gate._target_qudits],
) = Adaptive.execute()

# if self.verify:
# nodes = list(self.energy_level_graph.nodes)
# lpmap = list(self.energy_level_graph.log_phy_map)
#
# Vgate = deepcopy(gate_matrix)
# inode = self.energy_level_graph._1stInode
#
# if 'phase_storage' in self.energy_level_graph.nodes[inode]:
# for i in range(len(recover_dict)):
# if abs(recover_dict[i]) > 1.0e-4:
# phase_gate = Rz(-recover_dict[i], i, self.dimension) # logical rotation
# Vgate = Custom_Unitary(matmul(phase_gate.matrix, Vgate.matrix), self.dimension)
#
# V = Verifier(matrices_decomposed, Vgate, nodes, ini_lpmap, lpmap, self.dimension)
# Vr = V.verify()
#
# if not Vr:
# raise Exception
new_instructions += matrices_decomposed
# circuit.replace_gate(i, matrices_decomposed)
gate_trans = self.transpile_gate(gate)
new_instructions.extend(gate_trans)
gc.collect()
else:
new_instructions.append(gate) # TODO REENCODING
new_instructions.append(gate)
transpiled_circuit = self.circuit.copy()
return transpiled_circuit.set_instructions(new_instructions)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,25 @@ class PhyLocQRPass(CompilerPass):
def __init__(self, backend) -> None:
super().__init__(backend)

def transpile_gate(self, gate):
energy_graph_i = self.backend.energy_level_graphs[gate._target_qudits]
QR = PhyQrDecomp(gate, energy_graph_i, not_stand_alone=False)
decomp, _algorithmic_cost, _total_cost = QR.execute()
return [op.dag() for op in reversed(decomp)]

def transpile(self, circuit):
self.circuit = circuit
instructions = circuit.instructions
new_instructions = []

for gate in instructions:
if gate.gate_type == GateTypes.SINGLE:
energy_graph_i = self.backend.energy_level_graphs[gate._target_qudits]
QR = PhyQrDecomp(gate, energy_graph_i, not_stand_alone=False)
decomp, _algorithmic_cost, _total_cost = QR.execute()
new_instructions += decomp
gate_trans = self.transpile_gate(gate)
gate_trans = [op.dag() for op in reversed(gate_trans)]
new_instructions.extend(gate_trans)
gc.collect()
else:
new_instructions.append(gate) # TODO REENCODING
new_instructions.append(gate)
transpiled_circuit = self.circuit.copy()
return transpiled_circuit.set_instructions(new_instructions)

Expand Down Expand Up @@ -65,7 +70,7 @@ def execute(self):
"VRz",
self.gate._target_qudits,
[self.graph.nodes[i]["lpmap"], thetaZ],
self.gate.dimension,
self.gate._dimensions,
) # (thetaZ, self.graph.nodes[i]['lpmap'], dimension)
decomp.append(phase_gate)
recover_dict[i] = thetaZ
Expand Down
Loading
Loading