Skip to content

Commit ea2ec48

Browse files
committed
Draft support trappedions
* Add netsquid-trappedions snippet as a requirement * Register IonTrapIndividualAddressing as a qdevice model with the key "trapped-ion" * Add TrappedIonIndividualFlavour as flavour when using "trapped-ion" in handler * Add TISubroutineTranspiler as transpiler when using "trapped-ion" in host * Create TIProcessor class * Add TIProcessor as processor when using "trapped-ion" in qnos
1 parent 21b2404 commit ea2ec48

File tree

6 files changed

+102
-2
lines changed

6 files changed

+102
-2
lines changed

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ install_requires =
2222
pydynaa >=0.3, <2.0
2323
netsquid >=1.1.8, <2.0
2424
netsquid-magic >= 16.0.0, <17.0.0
25+
netsquid-trappedions >= 4.0.0, <5.0.0
2526
bitarray >=2.8.0, <3.0.0
2627
netqasm >=1.0.0, <=2.0.0
2728
pytest >=7.1, <8.0

squidasm/run/stack/build.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from netsquid_netbuilder.builder.network_builder import NetworkBuilder, NodeBuilder
66
from netsquid_netbuilder.network_config import NetworkConfig
77
from netsquid_netbuilder.run import get_default_builder
8+
from netsquid_trappedions.ion_trap import IonTrapIndividualAddressingBuilder
89

910
from squidasm.sim.stack.stack import StackNode
1011

@@ -36,6 +37,7 @@ def build(self, config: NetworkConfig) -> Dict[str, StackNode]:
3637

3738
def create_stack_network_builder() -> NetworkBuilder:
3839
builder = get_default_builder()
40+
builder.register_qdevice("trapped-ion", IonTrapIndividualAddressingBuilder)
3941
original_node_builder = builder.node_builder
4042

4143
# replace the original node builder with new StackNodeBuilder

squidasm/sim/stack/handler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ def __init__(
148148
self._flavour: Optional[flavour.Flavour] = flavour.NVFlavour()
149149
elif qdevice_type == "generic":
150150
self._flavour: Optional[flavour.Flavour] = flavour.VanillaFlavour()
151+
elif qdevice_type == "trapped-ion":
152+
self._flavour: Optional[
153+
flavour.Flavour
154+
] = flavour.TrappedIonIndividualFlavour()
151155
else:
152156
raise ValueError
153157

squidasm/sim/stack/host.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
StopAppMessage,
1010
)
1111
from netqasm.sdk.epr_socket import EPRSocket
12-
from netqasm.sdk.transpile import NVSubroutineTranspiler, SubroutineTranspiler
12+
from netqasm.sdk.transpile import (
13+
NVSubroutineTranspiler,
14+
SubroutineTranspiler,
15+
TISubroutineTranspiler,
16+
)
1317
from netsquid.components.component import Component, Port
1418
from netsquid.nodes import Node
1519

@@ -67,6 +71,8 @@ def __init__(self, comp: HostComponent, qdevice_type: Optional[str] = "nv") -> N
6771
] = NVSubroutineTranspiler
6872
elif qdevice_type == "generic":
6973
self._compiler: Optional[Type[SubroutineTranspiler]] = None
74+
elif qdevice_type == "trapped-ion":
75+
self._compiler = TISubroutineTranspiler
7076
else:
7177
raise ValueError
7278

squidasm/sim/stack/processor.py

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
from typing import TYPE_CHECKING, Dict, Generator, Optional, Union
55

66
import netsquid as ns
7-
from netqasm.lang.instr import NetQASMInstruction, core, nv, vanilla
7+
from netqasm.lang.instr import (
8+
NetQASMInstruction,
9+
core,
10+
nv,
11+
trapped_ion_individual,
12+
vanilla,
13+
)
814
from netqasm.lang.operand import Register
915
from netqasm.lang.subroutine import Subroutine
1016
from netsquid.components import QuantumProcessor
@@ -31,6 +37,7 @@
3137
from netsquid.components.qprogram import QuantumProgram
3238
from netsquid.nodes import Node
3339
from netsquid.qubits import qubitapi
40+
from netsquid_trappedions.instructions import INSTR_MS_INDIVIDUAL
3441

3542
from pydynaa import EventExpression
3643
from squidasm.sim.stack.common import (
@@ -883,3 +890,78 @@ def _interpret_controlled_rotation_instr(
883890
yield from self._do_controlled_rotation(app_id, instr, INSTR_CYDIR)
884891
else:
885892
raise RuntimeError(f"Unsupported instruction {instr}")
893+
894+
895+
class TIProcessor(Processor):
896+
"""A `Processor` for nodes with a TI hardware."""
897+
898+
def _interpret_qalloc(self, app_id: int, instr: core.QAllocInstruction) -> None:
899+
app_mem = self.app_memories[app_id]
900+
901+
virt_id = app_mem.get_reg_value(instr.reg)
902+
if virt_id is None:
903+
raise RuntimeError(f"qubit address in register {instr.reg} is not defined")
904+
self._logger.debug(f"Allocating qubit with virtual ID {virt_id}")
905+
906+
# All qubits are communication qubits in TI
907+
phys_id = self.physical_memory.allocate_comm()
908+
app_mem.map_virt_id(virt_id, phys_id)
909+
910+
def _interpret_init(
911+
self, app_id: int, instr: core.InitInstruction
912+
) -> Generator[EventExpression, None, None]:
913+
app_mem = self.app_memories[app_id]
914+
virt_id = app_mem.get_reg_value(instr.reg)
915+
phys_id = app_mem.phys_id_for(virt_id)
916+
self._logger.debug(
917+
f"Performing {instr} on virtual qubit "
918+
f"{virt_id} (physical ID: {phys_id})"
919+
)
920+
prog = QuantumProgram()
921+
prog.apply(INSTR_INIT, qubit_indices=[phys_id])
922+
yield self.qdevice.execute_program(prog)
923+
924+
def _interpret_meas(
925+
self, app_id: int, instr: core.MeasInstruction
926+
) -> Generator[EventExpression, None, None]:
927+
app_mem = self.app_memories[app_id]
928+
virt_id = app_mem.get_reg_value(instr.qreg)
929+
phys_id = app_mem.phys_id_for(virt_id)
930+
931+
self._logger.debug(
932+
f"Measuring qubit {virt_id} (physical ID: {phys_id}), "
933+
f"placing the outcome in register {instr.creg}"
934+
)
935+
936+
prog = QuantumProgram()
937+
prog.apply(INSTR_MEASURE, qubit_indices=[phys_id])
938+
yield self.qdevice.execute_program(prog)
939+
outcome: int = prog.output["last"][0]
940+
app_mem.set_reg_value(instr.creg, outcome)
941+
942+
def _interpret_single_rotation_instr(
943+
self, app_id: int, instr: trapped_ion_individual.RotXInstruction
944+
) -> Generator[EventExpression, None, None]:
945+
if isinstance(instr, trapped_ion_individual.RotXInstruction):
946+
yield from self._do_single_rotation(app_id, instr, INSTR_ROT_X)
947+
elif isinstance(instr, trapped_ion_individual.RotYInstruction):
948+
yield from self._do_single_rotation(app_id, instr, INSTR_ROT_Y)
949+
elif isinstance(instr, trapped_ion_individual.RotZInstruction):
950+
yield from self._do_single_rotation(app_id, instr, INSTR_ROT_Z)
951+
else:
952+
raise RuntimeError(f"Unsupported instruction {instr}")
953+
954+
def _interpret_two_qubit_instr(
955+
self, app_id: int, instr: core.TwoQubitRotationInstruction
956+
) -> Generator[EventExpression, None, None]:
957+
assert isinstance(instr, trapped_ion_individual.MSGateInstruction)
958+
959+
app_mem = self.app_memories[app_id]
960+
virt_id0 = app_mem.get_reg_value(instr.reg0)
961+
phys_id0 = app_mem.phys_id_for(virt_id0)
962+
virt_id1 = app_mem.get_reg_value(instr.reg1)
963+
phys_id1 = app_mem.phys_id_for(virt_id1)
964+
965+
prog = QuantumProgram()
966+
prog.apply(INSTR_MS_INDIVIDUAL, qubit_indices=[phys_id0, phys_id1])
967+
yield self.qdevice.execute_program(prog)

squidasm/sim/stack/qnos.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
NVProcessor,
2121
Processor,
2222
ProcessorComponent,
23+
TIProcessor,
2324
)
2425

2526
# TODO: make this a parameter
@@ -135,6 +136,10 @@ def __init__(self, comp: QnosComponent, qdevice_type: Optional[str] = "nv") -> N
135136
elif qdevice_type == "nv":
136137
self.processor = NVProcessor(comp.processor_comp, self)
137138
self._physical_memory = NVPhysicalQuantumMemory(comp.qdevice.num_positions)
139+
elif qdevice_type == "trapped-ion":
140+
self.processor = TIProcessor(comp.processor_comp, self)
141+
# We can use Generic PhysicalQuantumMemory for TI
142+
self._physical_memory = PhysicalQuantumMemory(comp.qdevice.num_positions)
138143
else:
139144
raise ValueError
140145

0 commit comments

Comments
 (0)