Source code for qudas.gate.ir

from qudas.gate.gate_ir import QdGateIR
from typing import List, Iterable


[docs]class QdAlgorithmIR: def __init__(self, gates: List[QdGateIR]): self.gates = gates
[docs] @classmethod def from_blocks(cls, blocks: Iterable[Iterable[QdGateIR]]): """量子回路ブロックの集合から ``QdAlgorithmIR`` を生成する。 Parameters ---------- blocks : Iterable[Iterable[QdGateIR]] 各ブロックが ``QdGateIR`` を要素にもつ反復可能オブジェクト。 典型的には :class:`qudas.gate.block.QdGateBlock` のリストを想定。 """ gates: List[QdGateIR] = [] for block in blocks: for gate in block: if isinstance(gate, QdGateIR): gates.append(gate) else: # 型が異なる場合はスキップ/将来拡張時に警告など continue return cls(gates=gates)
[docs] @classmethod def from_qasm(cls, qasm): """OpenQASM 文字列 / ファイルパス / QuantumCircuit から ``QdAlgorithmIR`` を生成する。 (QdGateIR ベース)""" from qiskit import QuantumCircuit # type: ignore import os if isinstance(qasm, QuantumCircuit): qc = qasm elif isinstance(qasm, str): if os.path.exists(qasm): qc = QuantumCircuit.from_qasm_file(qasm) else: qc = QuantumCircuit.from_qasm_str(qasm) else: raise TypeError(f"{type(qasm)} は対応していない型です。") gates: List[QdGateIR] = [] for inst, qargs, _ in qc.data: targets = [qc.qubits.index(q) for q in qargs] gate_ir = QdGateIR( gate=inst.name, targets=targets, controls=[], params=list(inst.parameters) if hasattr(inst, "parameters") else [], ) gates.append(gate_ir) return cls(gates=gates)
[docs] def to_qiskit(self): """保持している ``QdGateIR`` 一覧から ``qiskit.circuit.QuantumCircuit`` を生成する。""" from qiskit import QuantumCircuit # type: ignore from qiskit.circuit import Instruction # type: ignore from qiskit.circuit.library import XGate, HGate, CXGate, RZGate, RXGate, RYGate if not self.gates: return QuantumCircuit(0) # 回路に必要な量子ビット数を取得 max_index = max( ( max(g.targets + g.controls) if (g.targets or g.controls) else -1 for g in self.gates ) ) num_qubits = max_index + 1 # 測定ゲートがあるかどうか確認 has_measure = any(g.gate == "measure" for g in self.gates) if has_measure: qc = QuantumCircuit( num_qubits, num_qubits ) # qubits と同数の classical bits else: qc = QuantumCircuit(num_qubits) # 名前→ゲートオブジェクトの対応表 gate_map = { "x": XGate, "h": HGate, "cx": CXGate, "rz": RZGate, "rx": RXGate, "ry": RYGate, # 必要に応じて追加 } for g in self.gates: # 制御 -> ターゲット の順で並べる qubit_indices = g.controls + g.targets if g.gate == "measure": # targets[0] を qubit, 同じ index の classical bit に対応付け for t in g.targets: qc.measure(t, t) else: if g.gate in gate_map: gate = ( gate_map[g.gate](*g.params) if g.params else gate_map[g.gate]() ) qc.append(gate, [qc.qubits[i] for i in qubit_indices]) else: raise ValueError(f"Unsupported gate: {g.gate}") return qc