-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcircuit_converter.py
119 lines (109 loc) · 4.26 KB
/
circuit_converter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from __future__ import annotations
import math
import quimb as qu
import quimb.tensor as qtn
from qiskit import QuantumCircuit, qasm2
from qiskit._qasm2 import ( # pylint: disable=no-name-in-module
CustomInstruction,
OpCode,
bytecode_from_string,
)
from qiskit.circuit import library as lib
def circuit_to_quimb_tn(qc: QuantumCircuit) -> qtn.Circuit | None:
custom_instructions = tuple(qasm2.LEGACY_CUSTOM_INSTRUCTIONS)
bytecode = bytecode_from_string(
qc.qasm(),
[qasm2._normalize_path(path) for path in qasm2.LEGACY_INCLUDE_PATH],
[
CustomInstruction(x.name, x.num_params, x.num_qubits, x.builtin)
for x in custom_instructions
],
tuple(qasm2.LEGACY_CUSTOM_CLASSICAL),
strict=False,
)
# https://github.com/Qiskit/qiskit/blob/main/qiskit/qasm2/parse.py
gates = []
has_u, has_cx = False, False
for custom in custom_instructions:
gates.append(custom.constructor)
if custom.name == "U":
has_u = True
elif custom.name == "CX":
has_cx = True
if not has_u:
gates.append(lib.UGate)
if not has_cx:
gates.append(lib.CXGate)
circuit: qtn.Circuit | None = None
num_qubits = 0
bc = iter(bytecode)
for op in bc:
opcode = op.opcode
if opcode == OpCode.Gate:
if circuit is None:
circuit = qtn.Circuit(num_qubits)
gate_id, parameters, op_qubits = op.operands
gate = gates[gate_id]
# https://github.com/jcmgray/quimb/blob/main/quimb/tensor/circuit.py
if gate == lib.standard_gates.HGate:
circuit.apply_gate("H", *op_qubits)
elif gate == lib.standard_gates.IGate:
pass
elif gate == lib.standard_gates.RXGate:
circuit.apply_gate("RX", *parameters, *op_qubits)
elif gate == lib.standard_gates.RYGate:
circuit.apply_gate("RY", *parameters, *op_qubits)
elif gate == lib.standard_gates.RZGate:
circuit.apply_gate("RZ", *parameters, *op_qubits)
elif gate == lib.standard_gates.SwapGate:
circuit.apply_gate("SWAP", *parameters, *op_qubits)
elif gate == lib.standard_gates.PhaseGate:
circuit.apply_gate(qu.phase_gate(*parameters), *op_qubits)
elif gate == lib.standard_gates.SGate:
circuit.apply_gate("S", *op_qubits)
elif gate == lib.standard_gates.TGate:
circuit.apply_gate("T", *op_qubits)
elif gate == lib.standard_gates.TdgGate:
circuit.apply_gate("U1", -math.pi / 4, *op_qubits)
elif gate == lib.standard_gates.XGate:
circuit.apply_gate("X", *op_qubits)
elif gate == lib.standard_gates.YGate:
circuit.apply_gate("Y", *op_qubits)
elif gate == lib.standard_gates.ZGate:
circuit.apply_gate("Z", *op_qubits)
elif gate == lib.standard_gates.CXGate:
circuit.apply_gate("CX", *op_qubits)
elif gate == lib.standard_gates.CYGate:
circuit.apply_gate("CY", *op_qubits)
elif gate == lib.standard_gates.CZGate:
circuit.apply_gate("CZ", *op_qubits)
elif gate == lib.standard_gates.RZZGate:
circuit.apply_gate("RZZ", *parameters, *op_qubits)
else:
print(f"Not implemented for a gate: {gate}")
elif opcode == OpCode.ConditionedGate:
pass
elif opcode == OpCode.Measure:
pass
elif opcode == OpCode.ConditionedMeasure:
pass
elif opcode == OpCode.Reset:
pass
elif opcode == OpCode.ConditionedReset:
pass
elif opcode == OpCode.Barrier:
pass
elif opcode == OpCode.DeclareQreg:
_, size = op.operands
num_qubits += size
elif opcode == OpCode.DeclareCreg:
pass
elif opcode == OpCode.SpecialInclude:
pass
elif opcode == OpCode.DeclareGate:
pass
elif opcode == OpCode.DeclareOpaque:
pass
else:
raise ValueError(f"invalid operation: {op}")
return circuit