MCPcopy
hub / github.com/Qiskit/qiskit / from_bytecode

Function from_bytecode

qiskit/qasm2/parse.py:205–315  ·  view source on GitHub ↗

Loop through the Rust bytecode iterator `bytecode` producing a :class:`~qiskit.circuit.QuantumCircuit` instance from it. All the hard work is done in Rust space where operations are faster; here, we're just about looping through the instructions as fast as possible, doing as little calc

(bytecode, custom_instructions: Iterable[CustomInstruction])

Source from the content-addressed store, hash-verified

203
204
205def from_bytecode(bytecode, custom_instructions: Iterable[CustomInstruction]):
206 """Loop through the Rust bytecode iterator `bytecode` producing a
207 :class:`~qiskit.circuit.QuantumCircuit` instance from it. All the hard work is done in Rust
208 space where operations are faster; here, we're just about looping through the instructions as
209 fast as possible, doing as little calculation as we can in Python space. The Python-space
210 components are the vast majority of the runtime.
211
212 The "bytecode", and so also this Python function, is very tightly coupled to the output of the
213 Rust parser. The bytecode itself is largely defined by Rust; from Python space, the iterator is
214 over essentially a 2-tuple of `(opcode, operands)`. The `operands` are fixed by Rust, and
215 assumed to be correct by this function.
216
217 The Rust code is responsible for all validation. If this function causes any errors to be
218 raised by Qiskit (except perhaps for some symbolic manipulations of `Parameter` objects), we
219 should consider that a bug in the Rust code."""
220 # The method `QuantumCircuit._append` is a semi-public method, so isn't really subject to
221 # "protected access".
222
223 qc = QuantumCircuit()
224 qubits = []
225 clbits = []
226 gates = []
227 has_u, has_cx = False, False
228 for custom in custom_instructions:
229 gates.append(custom.constructor)
230 if custom.name == "U":
231 has_u = True
232 elif custom.name == "CX":
233 has_cx = True
234 if not has_u:
235 gates.append(lib.UGate)
236 if not has_cx:
237 gates.append(lib.CXGate)
238 # Pull this out as an explicit iterator so we can manually advance the loop in `DeclareGate`
239 # contexts easily.
240 bc = iter(bytecode)
241 for op in bc:
242 # We have to check `op.opcode` so many times, it's worth pulling out the extra attribute
243 # access. We should check the opcodes in order of their likelihood to be in the OQ2 program
244 # for speed. Gate applications are by far the most common for long programs. This function
245 # is deliberately long and does not use hashmaps or function lookups for speed in
246 # Python-space.
247 opcode = op.opcode
248 # `OpCode` is an `enum` in Rust, but its instances don't have the same singleton property as
249 # Python `enum.Enum` objects.
250 if opcode == OpCode.Gate:
251 gate_id, parameters, op_qubits = op.operands
252 qc._append(
253 CircuitInstruction(gates[gate_id](*parameters), [qubits[q] for q in op_qubits])
254 )
255 elif opcode == OpCode.ConditionedGate:
256 gate_id, parameters, op_qubits, creg, value = op.operands
257 with qc.if_test((qc.cregs[creg], value)):
258 gate = gates[gate_id](*parameters)
259 qc.append(gate, [qubits[q] for q in op_qubits])
260 elif opcode == OpCode.Measure:
261 qubit, clbit = op.operands
262 qc._append(CircuitInstruction(Measure(), (qubits[qubit],), (clbits[clbit],)))

Callers

nothing calls this directly

Calls 12

_appendMethod · 0.95
if_testMethod · 0.95
appendMethod · 0.95
add_registerMethod · 0.95
QuantumCircuitClass · 0.90
MeasureClass · 0.90
ResetClass · 0.90
BarrierClass · 0.90
CircuitInstructionClass · 0.85
_gate_builderFunction · 0.85
_opaque_builderFunction · 0.85
appendMethod · 0.45

Tested by

no test coverage detected