User Guide

Subpackages

QuantumCircuit

This module allows users to create and simulate quantum circuits with noise models based on IBM quantum machines. It provides methods for adding gates, executing the circuit with Monte-Carlo simulations, and visualizing the circuit. It considers both single and two-qubit gate errors as well as measurement errors.

Example

>>> from NoisyCircuits.QuantumCircuit import QuantumCircuit
>>> circuit = QuantumCircuit(num_qubits=3, noise_model=my_noise_model, backend_qpu_type='Heron', num_trajectories=1000)
>>> circuit.h(0)
>>> circuit.cx(0, 1)
>>> circuit.cx(1, 2)
>>> circuit.run_with_density_matrix(qubits=[0, 1, 2]) # Executes the circuit using the density matrix solver
[0.39841323, 0.00300163, 0.09303931, 0.00615167, 0.00616272, 0.09281154, 0.00300024, 0.39741967]
>>> circuit.execute(qubits=[0, 1, 2]) # Executes the circuit using the Monte-Carlo Wavefunction method
[0.39748485, 0.0037614 , 0.09168292, 0.00799886, 0.00746056, 0.09156762, 0.00367236, 0.39637143]
>>> circuit.run_pure_state(qubits=[0, 1, 2]) # Executes the circuit using the pure state solver
[0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5]
>>> circuit.shutdown() # Shutdown the Ray parallel execution environment
class NoisyCircuits.QuantumCircuit.QuantumCircuit(num_qubits: int, noise_model: dict, backend_qpu_type: str, num_trajectories: int, num_cores: int = 2, sim_backend: str = 'qulacs', jsonize: bool = False, verbose: bool = True, threshold: float = 1e-12)[source]

Bases: object

This class allows a user to create a quantum circuit with error model from IBM machines where selected gates (both parameterized and non-parameterized) are implemented as methods. The gate decomposition uses the basis gates of the IBM Eagle (\(\sqrt{X}\), \(X\), \(R_Z(\theta)\) and \(ECR\)) / Heron (\(\sqrt{X}\), \(X\), \(R_Z(\theta)\), \(R_X(\theta)\), \(CZ\) and \(RZZ(\theta)\)) QPUs.

Currently, it is only possible to apply a limited selection of single and two-qubit gates to the circuit simulation. For a full list of supported gates, please refer to the Decomposition NoisyCircuits.utils.Decomposition() class documentation.

Parameters:
  • num_qubits (int) – The number of qubits in the circuit.

  • noise_model (dict) – The noise model to be used for the circuit.

  • backend_qpu_type (str) – The IBM Backend Architecture type to be used (Eagle or Heron).

  • num_trajectories (int) – The number of trajectories for the Monte-Carlo simulation.

  • num_cores (int, optional) – The number of cores to use for parallel execution. Defaults to 2.

  • sim_backend (str, optional) – The simulation backend to use, either ‘qulacs’, ‘pennylane’, or ‘qiskit’. Defaults to ‘pennylane’.

  • jsonize (bool, optional) – If True, the circuit will be serialized to JSON format. Defaults to False.

  • verbose (bool, optional) – If False, suppresses detailed output during initialization. Defaults to True.

  • threshold (float, optional) – The threshold for noise application. Defaults to 1e-12.

Raises:
  • TypeError – Raised when the input parameters are of incorrect types. - num_qubits is not an integer. - noise_model is not a dictionary. - backend_qpu_type is not a string. - num_trajectories is not an integer. - num_cores is not an integer. - sim_backend is not a string. - jsonize is not a boolean. - verbose is not a boolean.

  • ValueError – Raised when the input parameters have invalid values. - num_qubits is not a positive integer. - backend_qpu_type is not one of the supported types (Eagle or Heron). - num_trajectories is less than 1. - threshold is not between 0 and 1 (exclusive). - num_cores is less than 1 or exceeds available CPU cores. - sim_backend is not one of the supported backends (qulacs, pennylane, qiskit).

available_sim_backends = ['qulacs', 'pennylane', 'qiskit']
basis_gates_set = {'eagle': {'basis_gates': [['rz', 'sx', 'x'], ['ecr']], 'gate_decomposition': <class 'NoisyCircuits.utils.EagleDecomposition.EagleDecomposition'>}, 'heron': {'basis_gates': [['rz', 'rx', 'sx', 'x'], ['cz', 'rzz']], 'gate_decomposition': <class 'NoisyCircuits.utils.HeronDecomposition.HeronDecomposition'>}}
draw_circuit(style: str = 'mpl') None[source]

Draws the quantum circuit.

Parameters:

style (str, optional) – The style of the drawing, either ‘mpl’ for matplotlib or ‘text’ for text-based representation. Defaults to ‘mpl’.

Raises:
  • TypeError – If style is not a string.

  • ValueError – If style is not one of [‘mpl’, ‘text’].

  • ValueError – If there are no instructions in the circuit to draw.

execute(qubits: list[int], num_trajectories: int | None = None) ndarray[source]

Executes the built quantum circuit with the specified noise model using the Monte-Carlo Wavefunction method.

Parameters:
  • qubits (list[int]) – The list of qubits to be measured.

  • num_trajectories (int) – The number of trajectories for the Monte-Carlo simulation (can be modified). Defaults to None and uses the class attribute. If specified, it overrides the class attribute for only this execution. Defaults to None.

Raises:
  • TypeError – If qubits is not a list or the items in the list are not integers.

  • TypeError – If num_trajectories is not an integer.

  • ValueError – If num_trajectories is less than 1.

  • ValueError – If qubits contains invalid qubit indices.

  • ValueError – If there are no instructions in the circuit to execute.

Returns:

The probabilities of the output states.

Return type:

np.ndarray

refresh()[source]

Resets the quantum circuit by clearing the instruction list and qubit-to-instruction mapping.

run_pure_state(qubits: list[int]) ndarray[source]

Runs the quantum circuit with the pure state solver.

Parameters:

qubits (list[int]) – List of qubits to be simulated.

Raises:
  • TypeError – If qubits is not a list or the items in the list are not integers.

  • ValueError – If qubits contains invalid qubit indices.

  • ValueError – If there are no instructions in the circuit to execute.

Returns:

Probabilities of the output states.

Return type:

np.ndarray

run_with_density_matrix(qubits: list[int]) ndarray[source]

Runs the quantum circuit with the density matrix solver.

Parameters:

qubits (list[int]) – List of qubits to be simulated.

Raises:
  • TypeError – If qubits is not a list or the items in the list are not integers.

  • ValueError – If qubits contains invalid qubit indices.

  • ValueError – If there are no instructions in the circuit to execute.

Returns:

Probabilities of the output states.

Return type:

np.ndarray

shutdown()[source]

Shutsdown the Ray parallel execution environment.

property sim_backend: str

Getter for the _sim_backend attribute

Returns:

Returns the current sim_backend value.

Return type:

(str)

RunOnHardware

This module contains the RunOnHardware class which allows users to run quantum circuits on IBM Quantum Hardware. The class provides methods to create circuits (according to hardware requirements), set them up for execution, submit them to the hardware, check job status, cancel jobs, and retrieve results. IBM Quantum’s Qiskit Runtime Service is utilized for backend communication and job management. The retrieved results are formatted as probability distributions from little Endian format to big Endian format for easy analysis.

Example usage:
>>> from NoisyCircuits.RunOnHardware import RunOnHardware
>>> from NoisyCircuits.QuantumCircuit import QuantumCircuit
>>> circuit = QuantumCircuit(num_qubits=2, noise_model=noise_model, num_cores=2, num_trajectories=100)
>>> circuit.H(qubit=0)
>>> circuit.CX(control=0, target=1)
>>> runner = RunOnHardware(token=your_token, backend="ibm_fez", shots=1024)
>>> runner.create_circuits(circuit=circuit, measure_qubits=[0, 1])
>>> runner.setup_circuits()
>>> job_id = runner.run()
>>> status = runner.status(job_id=job_id)
'DONE'
>>> results = runner.get_results(job_id=job_id)
>>> circuit.execute(qubits=[0, 1])
[0.40313749, 0.09695667, 0.09692287, 0.40298296]
>>> print(results)
[0.40813749, 0.09195667, 0.10892288, 0.39098296]

It should be noted that the IBM Quantum backends have a maximum limit of 10,000,000 circuit executions per job submission. Users should ensure that the product of the number of circuits and shots does not exceed this limit to avoid job submission errors.

class NoisyCircuits.RunOnHardware.RunOnHardware(token: str | None = None, backend: str | None = None, shots: int | None = None)[source]

Bases: object

A class to run quantum circuits on IBM Quantum Hardware.

Parameters:
  • token (str) – IBM Quantum token.

  • backend (str) – Backend name.

  • shots (int) – Number of shots.

Raises:
  • ValueError – When the token, backend or shots are not provided.

  • TypeError – When the token, backend or shots are not of the expected type -> (str, str, int) respectively.

  • ValueError – When the shots are less than or equal to zero.

  • ValueError – When the backend is not available.

cancel(job_id: str | None = None) None[source]

Method to cancel the submitted job.

Parameters:

job_id (str, optional) – The Job Id for the submitted batch of PUBs. If not provided, uses the last submitted job_id provided the class object is not destroyed.

Raises:
  • TypeError – When the job_id is not of the expected type -> str.

  • ValueError – When the job_id is not provided and the class object is destroyed.

create_circuits(circuit: QuantumCircuit | None = None, measure_qubits: list[int] | None = None) None[source]

Method that generates the fully decomposed circuit list in qiskit for IBM Hardware execution.

Parameters:
  • circuit (NoisyCircuit.QuantumCircuit.QuantumCircuit) – The quantum circuit to add in qiskit version.

  • measure_qubits (list[int]) – The list of qubits to measure.

Raises:
  • ValueError – When the circuit is not provided.

  • TypeError – When the circuit is not of the expected type -> NoisyCircuits.QuantumCircuit.

  • TypeError – When the measure_qubits is not of the expected type -> list.

  • TypeError – When the elements of measure_qubits are not of the expected type -> int.

  • ValueError – When the circuit is empty.

  • ValueError – When the measure_qubits contain invalid qubit indices.

  • ValueError – When the circuit contains gates that are not in the backend’s basis gates.

get_results(job_id: str | None = None) list[ndarray][source]

Method that retrieves the results of the submitted job.

Parameters:

job_id (str, optional) – The Job Id for the submitted batch of PUBs. If not provided, uses the last submitted job_id provided the class object is not destroyed.

Raises:
  • TypeError – When the job_id is not of the expected type -> str.

  • ValueError – When the job_id is not provided and the class object is destroyed.

Returns:

The results of the submitted job. The list contains probabilities of the quantum circuit and the ordering is as inputted into the PUBs.

Return type:

list[np.ndarray]

run() str[source]

Method that submits the generated PUB for execution on the IBM Hardware.

Raises:

ValueError – When the maximum circuit execution limit of 10,000,000 is exceeded.

Returns:

Returns the Job Id for the submitted batch of PUBs for retrieval.

Return type:

str

setup_circuits() None[source]

Method that generates the PUB for the circuit list for execution on the IBM Hardware.

status(job_id: str | None = None) str[source]

Method that retrieves the status of the submitted job.

Parameters:

job_id (str, optional) – The Job Id for the submitted batch of PUBs. If not provided, uses the last submitted job_id provided the class object is not destroyed.

Raises:
  • TypeError – When the job_id is not of the expected type -> str.

  • ValueError – When the job_id is not provided and the class object is destroyed.

Returns:

The status of the submitted job.

Return type:

str