Skip to content

Commit 5716f2e

Browse files
Add the new gates to instruction log, add pytket output test for them
1 parent a61952b commit 5716f2e

File tree

3 files changed

+371
-1
lines changed

3 files changed

+371
-1
lines changed

selene-sim/python/selene_sim/event_hooks/instruction_log.py

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from enum import Enum
1313
from dataclasses import dataclass
1414
from collections.abc import Iterator
15-
from typing import Any
15+
from typing import Any, Optional
1616
import math
1717

1818
from .event_hook import EventHook
@@ -300,6 +300,133 @@ def from_iterator(it: Iterator):
300300
return FutureRead(qubit=next(it))
301301

302302

303+
RPP_PYTKET_DEFINITION: Optional["pytket.circuit.CustomGateDef"] = None
304+
305+
306+
@dataclass
307+
class RPP(Operation):
308+
qubit0: int
309+
qubit1: int
310+
theta: float
311+
phi: float
312+
313+
@staticmethod
314+
def get_gate_definition() -> "pytket.circuit.CustomGateDef":
315+
assert PYTKET_AVAILABLE, "pytket is not available"
316+
import sympy
317+
318+
global RPP_PYTKET_DEFINITION
319+
if RPP_PYTKET_DEFINITION is not None:
320+
return RPP_PYTKET_DEFINITION
321+
theta, phi = sympy.symbols("theta phi")
322+
subcircuit = pytket.Circuit(2)
323+
subcircuit.Rz(angle=-phi, qubit=0)
324+
subcircuit.Rz(angle=-phi, qubit=1)
325+
subcircuit.XXPhase(angle=theta, qubit0=0, qubit1=1)
326+
subcircuit.Rz(angle=phi, qubit=0)
327+
subcircuit.Rz(angle=phi, qubit=1)
328+
RPP_PYTKET_DEFINITION = pytket.circuit.CustomGateDef.define(
329+
name="PhasedXX", circ=subcircuit, args=[theta, phi]
330+
)
331+
return RPP_PYTKET_DEFINITION
332+
333+
def append_to_circuit(self, circuit: "pytket.Circuit"):
334+
assert PYTKET_AVAILABLE, "pytket is not available"
335+
circuit.add_custom_gate(
336+
definition=self.get_gate_definition(),
337+
params=[self.theta / math.pi, self.phi / math.pi],
338+
qubits=[self.qubit0, self.qubit1],
339+
)
340+
341+
def to_dict(self) -> dict:
342+
return {
343+
"op": "RPP",
344+
"qubit0": self.qubit0,
345+
"qubit1": self.qubit1,
346+
"theta": self.theta,
347+
"phi": self.phi,
348+
}
349+
350+
@staticmethod
351+
def from_iterator(it: Iterator):
352+
qubit0 = next(it)
353+
qubit1 = next(it)
354+
theta = next(it)
355+
phi = next(it)
356+
return RPP(qubit0=qubit0, qubit1=qubit1, theta=theta, phi=phi)
357+
358+
359+
@dataclass
360+
class TK2(Operation):
361+
qubit0: int
362+
qubit1: int
363+
alpha: float
364+
beta: float
365+
gamma: float
366+
367+
def append_to_circuit(self, circuit: "pytket.Circuit"):
368+
assert PYTKET_AVAILABLE, "pytket is not available"
369+
circuit.tk2(
370+
angle0=self.alpha / math.pi,
371+
angle1=self.beta / math.pi,
372+
angle2=self.gamma / math.pi,
373+
qubit0=self.qubit0,
374+
qubit1=self.qubit1,
375+
)
376+
377+
def to_dict(self) -> dict:
378+
return {
379+
"op": "TK2",
380+
"qubit0": self.qubit0,
381+
"qubit1": self.qubit1,
382+
"alpha": self.alpha,
383+
"beta": self.beta,
384+
"gamma": self.gamma,
385+
}
386+
387+
@staticmethod
388+
def from_iterator(it: Iterator):
389+
qubit0 = next(it)
390+
qubit1 = next(it)
391+
alpha = next(it)
392+
beta = next(it)
393+
gamma = next(it)
394+
return TK2(qubit0=qubit0, qubit1=qubit1, alpha=alpha, beta=beta, gamma=gamma)
395+
396+
397+
@dataclass
398+
class TwinRXY(Operation):
399+
qubit0: int
400+
qubit1: int
401+
theta: float
402+
phi: float
403+
404+
def append_to_circuit(self, circuit: "pytket.Circuit"):
405+
assert PYTKET_AVAILABLE, "pytket is not available"
406+
circuit.add_gate(
407+
pytket.OpType.NPhasedX,
408+
angles=[self.theta / math.pi, self.phi / math.pi],
409+
qubits=[self.qubit0, self.qubit1],
410+
)
411+
412+
def to_dict(self) -> dict:
413+
return {
414+
"op": "TwinRXY",
415+
"qubit0": self.qubit0,
416+
"qubit1": self.qubit1,
417+
"theta": self.theta,
418+
"phi": self.phi,
419+
}
420+
421+
@staticmethod
422+
def from_iterator(it: Iterator):
423+
qubit0 = next(it)
424+
qubit1 = next(it)
425+
theta = next(it)
426+
phi = next(it)
427+
return TwinRXY(qubit0=qubit0, qubit1=qubit1, theta=theta, phi=phi)
428+
429+
303430
class Source(Enum):
304431
"""
305432
Selene provides the source of each instruction as an
@@ -370,6 +497,12 @@ class itself, and it is responsible for advancing the iterator
370497
operation = GlobalBarrier.from_iterator(it)
371498
case 12:
372499
operation = MeasureLeakedRequest.from_iterator(it)
500+
case 13:
501+
operation = RPP.from_iterator(it)
502+
case 14:
503+
operation = TK2.from_iterator(it)
504+
case 15:
505+
operation = TwinRXY.from_iterator(it)
373506
if operation is None:
374507
raise ValueError(f"Unknown instruction operation index {operation_idx}")
375508
return Instruction(source=source, operation=operation)

0 commit comments

Comments
 (0)