Source code for vulqano.circuit_tester.read_qasm

# This code is part of vulqano.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
Module for reading the qasm file creating a noisy circuit
"""

from ast import literal_eval
import numpy as np


try:
    from qmatchatea.circuit import Qcircuit
except ImportError:
    Qcircuit = None

__all__ = ["read_qasm_function"]


[docs] def read_qasm_function(filename, operations): """ Read a qasm file and build a Qcircuit object for the qmatchatea simulation. Works only when a single register is there. **Arguments** filename: str Filename of the qasm file to read operations: DiscreteOperations Operations class to handle the noise **Returns** Qcircuit A Quantum circuit class to run with qmatchatea representing a single trajectory """ if Qcircuit is None: raise ImportError("Please install qmatchatea.") with open(filename, "r") as qfh: # Read header header = qfh.readline()[:-1].split() version = float(header[-1][:-1]) if not np.isclose(version, 2.0): raise ValueError(f"The only QASM version supported is 2.0, not {version}") # Read all the includes line = qfh.readline()[:-1].split() while line[0] == "include": line = qfh.readline()[:-1].split() # Read the quantum register qreg = line[1][:-1].replace("q", "").replace("[", "").replace("]", "") num_qubits = int(qreg) # Read the classical register creg = qfh.readline().replace(";", "").split() if creg[0] == "creg": _ = int(creg[1][:-1][2]) # Number of bits # The circuit starts now line = qfh.readline().replace(";", "").split() else: line = creg # Initialization of the circuit qcirc = Qcircuit(num_qubits) # Cycle over all the lines while len(line) > 0: # We need this to later add identities where nothing is applied filled_idxs = [] # A comment means a new layer while line[0] != "#": gate = _read_gate(line) qubits = _read_qubits(line) filled_idxs += qubits # Crosstalk is treated as a gate # with its weight as parameter # Add the operation to the circuit qcirc.add(operations[gate], qubits) # Read the new line line = qfh.readline().replace(";", "").split() if len(line) == 0: break # Fill with identities all the empty spaces in the current layer if operations.weights_dict["I"] != 0: empty_idxs = np.setdiff1d(np.arange(num_qubits), np.array(filled_idxs)) for qubit in empty_idxs: qcirc.add(operations["i"], [qubit]) # Read next line in the circuit line = qfh.readline().replace(";", "").split() return qcirc
def _read_gate(line): """ Read a gate, understanding if it is parametric, from a qasm line **Arguments** line: List[str] List of strings. The line where the split() method was called **Returns** str | Tuple[str, List[float]] The gate identifiear and its parameters (if any) """ gate = line[0] # The gate is parametric if "(" in line[0]: gate = gate.split("(") # Up to ")", which is the last character params = gate[1][:-1].split(",") params = [literal_eval(pp) for pp in params] gate = (gate[0], params) else: gate = (gate, []) return gate def _read_qubits(line): """ Read the qubits to which a gate is applied from a qasm line **Arguments** line: List[str] List of strings. The line where the split() method was called **Returns** List[int] The list of qubit indexes """ qubits = "".join(line[1:]).replace("q", "").replace("[", "").replace("]", "") qubits = qubits.split(",") qubits = [int(qq) for qq in qubits if len(qq) > 0] return qubits