Skip to content

Commit

Permalink
Create REIDSFlavour and REIDSSubroutineTranspiler
Browse files Browse the repository at this point in the history
  • Loading branch information
Thom747 committed Mar 5, 2024
1 parent 06bef47 commit a781176
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 34 deletions.
9 changes: 9 additions & 0 deletions netqasm/lang/instr/flavour.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,12 @@ def instrs(self):

def __init__(self):
super().__init__(self.instrs)


class REIDSFlavour(Flavour):
@property
def instrs(self):
return []

def __init__(self):
super().__init__(self.instrs)
112 changes: 78 additions & 34 deletions netqasm/sdk/transpile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from typing import Dict, List, Optional, Set, Tuple, Union

from netqasm.lang.instr import DebugInstruction, NetQASMInstruction, core, nv, vanilla
from netqasm.lang.instr.flavour import REIDSFlavour
from netqasm.lang.operand import Immediate, Register, RegisterName
from netqasm.lang.subroutine import Subroutine
from netqasm.runtime.settings import get_is_using_hardware
Expand All @@ -17,7 +18,8 @@

class SubroutineTranspiler(abc.ABC):
def __init__(self, subroutine: Subroutine, debug: bool = False):
pass
self._subroutine: Subroutine = subroutine
self._debug: bool = debug

@abc.abstractmethod
def transpile(self) -> Subroutine:
Expand All @@ -31,10 +33,9 @@ class NVSubroutineTranspiler(SubroutineTranspiler):
"""

def __init__(self, subroutine: Subroutine, debug=False):
self._subroutine: Subroutine = subroutine
super().__init__(subroutine, debug)
self._used_registers: Set[Register] = set()
self._register_values: Dict[Register, Immediate] = dict()
self._debug: bool = debug

def get_reg_value(self, reg: Register) -> Immediate:
"""Get the value of a register at this moment"""
Expand All @@ -51,10 +52,10 @@ def get_unused_register(self) -> Register:
raise RuntimeError("Could not find free register")

def swap(
self,
lineno: Optional[HostLine],
electron: Register,
carbon: Register,
self,
lineno: Optional[HostLine],
electron: Register,
carbon: Register,
) -> List[NetQASMInstruction]:
"""
Swap the states of the electron and a carbon.
Expand Down Expand Up @@ -159,7 +160,7 @@ def transpile(self) -> Subroutine:
index_changes[i] = len(new_commands)

if isinstance(instr, core.SingleQubitInstruction) or isinstance(
instr, core.RotationInstruction
instr, core.RotationInstruction
):
new_commands += self._handle_single_qubit_gate(instr)
elif isinstance(instr, core.TwoQubitInstruction):
Expand All @@ -171,9 +172,9 @@ def transpile(self) -> Subroutine:

for instr in new_commands:
if (
isinstance(instr, core.BranchUnaryInstruction)
or isinstance(instr, core.BranchBinaryInstruction)
or isinstance(instr, core.JmpInstruction)
isinstance(instr, core.BranchUnaryInstruction)
or isinstance(instr, core.BranchBinaryInstruction)
or isinstance(instr, core.JmpInstruction)
):
original_line = instr.line.value
if original_line == len(self._subroutine.instructions):
Expand All @@ -196,7 +197,7 @@ def transpile(self) -> Subroutine:
return self._subroutine

def _move_electron_carbon(
self, instr: vanilla.MovInstruction
self, instr: vanilla.MovInstruction
) -> List[NetQASMInstruction]:
"""
See https://gitlab.tudelft.nl/qinc-wehner/netqasm/netqasm-docs/-/blob/master/nv-gates-docs.md
Expand Down Expand Up @@ -228,7 +229,7 @@ def _move_electron_carbon(
]

def _move_carbon_electron(
self, instr: vanilla.MovInstruction
self, instr: vanilla.MovInstruction
) -> List[NetQASMInstruction]:
"""
See https://gitlab.tudelft.nl/qinc-wehner/netqasm/netqasm-docs/-/blob/master/nv-gates-docs.md
Expand Down Expand Up @@ -266,7 +267,7 @@ def _move_carbon_electron(
]

def _handle_two_qubit_gate(
self, instr: core.TwoQubitInstruction
self, instr: core.TwoQubitInstruction
) -> List[NetQASMInstruction]:
try:
qubit_id0 = self.get_reg_value(instr.reg0).value
Expand Down Expand Up @@ -312,8 +313,8 @@ def _handle_two_qubit_gate(
)

def _map_cphase_electron_carbon(
self,
instr: vanilla.CphaseInstruction,
self,
instr: vanilla.CphaseInstruction,
) -> List[NetQASMInstruction]:
electron = instr.reg0
carbon = instr.reg1
Expand Down Expand Up @@ -345,7 +346,7 @@ def _map_cphase_electron_carbon(
]

def _map_cphase_carbon_carbon(
self, instr: vanilla.CphaseInstruction
self, instr: vanilla.CphaseInstruction
) -> List[NetQASMInstruction]:
"""
See https://gitlab.tudelft.nl/qinc-wehner/netqasm/netqasm-docs/-/blob/master/nv-gates-docs.md
Expand All @@ -360,15 +361,15 @@ def _map_cphase_carbon_carbon(

result: List[NetQASMInstruction] = [set_electron]
result += (
self.swap(instr.lineno, electron, carbon)
+ self._map_cphase_electron_carbon(instr)
+ self.swap(instr.lineno, electron, carbon)
self.swap(instr.lineno, electron, carbon)
+ self._map_cphase_electron_carbon(instr)
+ self.swap(instr.lineno, electron, carbon)
)
return result

def _map_cnot_electron_carbon(
self,
instr: vanilla.CnotInstruction,
self,
instr: vanilla.CnotInstruction,
) -> List[NetQASMInstruction]:
electron = instr.reg0
carbon = instr.reg1
Expand All @@ -394,8 +395,8 @@ def _map_cnot_electron_carbon(
]

def _map_cnot_carbon_electron(
self,
instr: vanilla.CnotInstruction,
self,
instr: vanilla.CnotInstruction,
) -> List[NetQASMInstruction]:
"""
See https://gitlab.tudelft.nl/qinc-wehner/netqasm/netqasm-docs/-/blob/master/nv-gates-docs.md
Expand Down Expand Up @@ -436,7 +437,7 @@ def _map_cnot_carbon_electron(
return gates

def _map_cnot_carbon_carbon(
self, instr: vanilla.CnotInstruction
self, instr: vanilla.CnotInstruction
) -> List[NetQASMInstruction]:
"""
See https://gitlab.tudelft.nl/qinc-wehner/netqasm/netqasm-docs/-/blob/master/nv-gates-docs.md
Expand All @@ -451,21 +452,21 @@ def _map_cnot_carbon_carbon(

result: List[NetQASMInstruction] = [set_electron]
result += (
self.swap(instr.lineno, electron, carbon)
+ self._map_cnot_electron_carbon(instr)
+ self.swap(instr.lineno, electron, carbon)
self.swap(instr.lineno, electron, carbon)
+ self._map_cnot_electron_carbon(instr)
+ self.swap(instr.lineno, electron, carbon)
)
return result

def _handle_single_qubit_gate(
self,
instr: Union[core.SingleQubitInstruction, core.RotationInstruction],
self,
instr: Union[core.SingleQubitInstruction, core.RotationInstruction],
) -> List[NetQASMInstruction]:
return self._map_single_gate(instr)

def _map_single_gate(
self,
instr: Union[core.SingleQubitInstruction, core.RotationInstruction],
self,
instr: Union[core.SingleQubitInstruction, core.RotationInstruction],
) -> List[NetQASMInstruction]:
if isinstance(instr, vanilla.GateXInstruction):
return [
Expand Down Expand Up @@ -614,14 +615,57 @@ def _map_single_gate(
)


class REIDSSubroutineTranspiler(SubroutineTranspiler):
"""
A transpiler that converts a subroutine with the vanilla flavour
to a subroutine with the REIDS flavour.
"""

def __init__(self, subroutine: Subroutine, debug: bool = False):
super().__init__(subroutine, debug)
self._flavour = REIDSFlavour()

def transpile(self) -> Subroutine:
add_no_op_at_end: bool = False

for instr in self._subroutine.instructions:
try:
self._flavour.id_map[instr.id]
except KeyError as e:
raise ValueError(
f"Instruction {instr} not supported: Unsupported instruction for REIDS flavour."
) from e

if (
isinstance(instr, core.BranchUnaryInstruction)
or isinstance(instr, core.BranchBinaryInstruction)
or isinstance(instr, core.JmpInstruction)
):
original_line = instr.line.value
if original_line == len(self._subroutine.instructions):
# There was a label in the original subroutine at the very end.
# Since this label is now removed, we should put a "no-op"
# instruction there so there is something to jump to.
add_no_op_at_end = True

if add_no_op_at_end:
self._subroutine.instructions += [
core.SetInstruction(
lineno=None, reg=Register(RegisterName.C, 15), imm=Immediate(1337)
)
]

return self._subroutine


def get_hardware_num_denom(
instr: core.RotationInstruction,
instr: core.RotationInstruction,
) -> Tuple[Immediate, Immediate]:
if instr.angle_denom.value not in [0, 1, 2, 3, 4]:
raise ValueError(
f"Instruction {instr} not supported: angle_denom is {instr.angle_denom}."
)

denom_diff = 4 - instr.angle_denom.value
angle_num = instr.angle_num.value * (2**denom_diff)
angle_num = instr.angle_num.value * (2 ** denom_diff)
return (Immediate(angle_num), Immediate(4))

0 comments on commit a781176

Please sign in to comment.