C3 Simulator as a backend for Qiskit Experiments

This notebook demonstrates the use of the C3 Simulator with a high-level quantum programming framework Qiskit. You must additionally install qiskit and matplotlib to run this example.

!pip install -q qiskit matplotlib
from pprint import pprint
import numpy as np
from c3.qiskit import C3Provider
from c3.qiskit.c3_gates import RX90pGate
from qiskit import transpile, execute, QuantumCircuit, Aer
from qiskit.tools.visualization import plot_histogram

Define a basic Quantum circuit

qc = QuantumCircuit(3, 3)
qc.append(RX90pGate(), [0])
qc.append(RX90pGate(), [1])
<qiskit.circuit.instructionset.InstructionSet at 0x17b189980>
q_0: ┤ Rx90p(π/2) ├
q_1: ┤ Rx90p(π/2) ├
q_2: ──────────────

c: 3/══════════════

Get the C3 Provider and Backend

c3_provider = C3Provider()
c3_backend = c3_provider.get_backend("c3_qasm_physics_simulator")
config = c3_backend.configuration()

print("Name: {0}".format(config.backend_name))
print("Version: {0}".format(config.backend_version))
print("Max Qubits: {0}".format(config.n_qubits))
print("OpenPulse Support: {0}".format(config.open_pulse))
print("Basis Gates: {0}".format(config.basis_gates))
Name: c3_qasm_physics_simulator
Version: 0.1
Max Qubits: 10
OpenPulse Support: False
Basis Gates: ['cx', 'rx']

Run a physical device simulation using C3

c3_job = c3_backend.run(qc)
result = c3_job.result()
No measurements in circuit "circuit-0", classical register will remain all zeros.
2022-01-01 03:30:00.931206: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)
2022-01-01 03:30:00.933640: W tensorflow/core/platform/profile_utils/cpu_utils.cc:128] Failed to get CPU frequency: 0 Hz
res_counts = result.get_counts()
{'000': 0.2501927838288728,
 '001': 1.6223933410984962e-29,
 '010': 0.27496041223138323,
 '011': 1.1175740719685343e-31,
 '100': 0.25116573990906244,
 '101': 2.4732633272223437e-33,
 '110': 0.22368106403066923,
 '111': 6.525386280486658e-35}
plot_histogram(res_counts, title='C3 Physical Device simulation')

As we can see above, the c3 simulator correctly calculates the populations while accounting for non-optimal pulses and device limitations.

Run Simulation and verify results on Qiskit simulator

Qiskit uses little-endian bit ordering while most Quantum Computing literature uses big-endian. This is reflected in the reversed ordering of qubit labels here.

Ref: Basis Vector Ordering in Qiskit

qiskit_simulator = Aer.get_backend('qasm_simulator')
qc.measure([0, 1, 2], [0, 1, 2])
qiskit_result = execute(qc, qiskit_simulator, shots=1000).result()
counts = qiskit_result.get_counts(qc)
plot_histogram(counts, title='Qiskit simulation')
/opt/homebrew/Caskroom/miniforge/base/envs/c3-dev/lib/python3.8/site-packages/numpy/linalg/linalg.py:2159: RuntimeWarning: divide by zero encountered in det
  r = _umath_linalg.det(a, signature=signature)
/opt/homebrew/Caskroom/miniforge/base/envs/c3-dev/lib/python3.8/site-packages/numpy/linalg/linalg.py:2159: RuntimeWarning: invalid value encountered in det
  r = _umath_linalg.det(a, signature=signature)