|
14 | 14 |
|
15 | 15 | # RUN: %PYTHON %s | FileCheck %s
|
16 | 16 |
|
| 17 | +import os |
| 18 | +import pathlib |
| 19 | +import platform |
| 20 | + |
17 | 21 | import numpy as np
|
18 | 22 | import pennylane as qml
|
| 23 | +from pennylane.devices.capabilities import OperatorProperties |
19 | 24 |
|
20 | 25 | from catalyst import measure, qjit
|
| 26 | +from catalyst.compiler import get_lib_path |
| 27 | +from catalyst.device import get_device_capabilities |
| 28 | + |
| 29 | +TEST_PATH = os.path.dirname(__file__) |
| 30 | +CONFIG_CUSTOM_DEVICE = pathlib.Path(f"{TEST_PATH}/../custom_device/custom_device.toml") |
21 | 31 |
|
22 | 32 |
|
23 | 33 | # CHECK-LABEL: public @jit_circuit
|
@@ -63,18 +73,48 @@ def circuit():
|
63 | 73 |
|
64 | 74 | print(circuit.mlir)
|
65 | 75 |
|
66 |
| -""" |
67 |
| -# TODO: The only reason we are using the braket.local.qubit device here |
68 |
| -# is because this test was developed before having support for custom devices. |
69 |
| -# We should replace instead create a custom device that has support for ISWAP |
70 |
| -# and PSWAP (which I think are unsupported in lightning.qubit and hence why they |
71 |
| -# would be decomposed. |
72 |
| -""" |
| 76 | + |
| 77 | +def get_custom_qjit_device(num_wires, discards, additions): |
| 78 | + """Generate a custom device without gates in discards.""" |
| 79 | + |
| 80 | + class CustomDevice(qml.devices.Device): |
| 81 | + """Custom Gate Set Device""" |
| 82 | + |
| 83 | + name = "lightning.qubit" |
| 84 | + config_filepath = CONFIG_CUSTOM_DEVICE |
| 85 | + |
| 86 | + def __init__(self, shots=None, wires=None): |
| 87 | + super().__init__(wires=wires, shots=shots) |
| 88 | + self.qjit_capabilities = get_device_capabilities(self) |
| 89 | + for gate in discards: |
| 90 | + self.qjit_capabilities.operations.pop(gate, None) |
| 91 | + self.qjit_capabilities.operations.update(additions) |
| 92 | + |
| 93 | + @staticmethod |
| 94 | + def get_c_interface(): |
| 95 | + """Returns a tuple consisting of the device name, and |
| 96 | + the location to the shared object with the C/C device implementation. |
| 97 | + """ |
| 98 | + |
| 99 | + system_extension = ".dylib" if platform.system() == "Darwin" else ".so" |
| 100 | + # Borrowing the NullQubit library: |
| 101 | + lib_path = ( |
| 102 | + get_lib_path("runtime", "RUNTIME_LIB_DIR") + "/librtd_null_qubit" + system_extension |
| 103 | + ) |
| 104 | + return "NullQubit", lib_path |
| 105 | + |
| 106 | + def execute(self, circuits, execution_config): |
| 107 | + """Exececute the device (no).""" |
| 108 | + raise RuntimeError("No execution for the custom device") |
| 109 | + |
| 110 | + return CustomDevice(wires=num_wires) |
73 | 111 |
|
74 | 112 |
|
75 | 113 | # CHECK-LABEL: public @jit_circuit
|
76 | 114 | @qjit(target="mlir")
|
77 |
| -@qml.qnode(qml.device("braket.local.qubit", wires=2, shots=100)) |
| 115 | +@qml.qnode( |
| 116 | + get_custom_qjit_device(2, (), {"ISWAP": OperatorProperties(), "PSWAP": OperatorProperties()}) |
| 117 | +) |
78 | 118 | def circuit(x: float):
|
79 | 119 | # CHECK: {{%.+}} = quantum.custom "ISWAP"() {{.+}} : !quantum.bit, !quantum.bit
|
80 | 120 | qml.ISWAP(wires=[0, 1])
|
|
0 commit comments