Using Logical and Physical Simulators
In this notebook, we provide a short demo for using the logical and physical simulators, as well as using different simulation backends for the logical/physical simulators.
To run this notebook with the appropriate dependencies, you can run
pip install "bloqade-lanes[sim, clifft]"
If you would like to run simulation with PPVM (which is still in development and has not been released), you can install PPVM with the following command:
pip install "ppvm @ git+https://github.com/QuEraComputing/ppvm.git@ff6bbb558cc9593adcde9a0668edbe3c0fee1ab4#subdirectory=ppvm-python"
Constructing Simulators
Section titled “Constructing Simulators”We have two different simulators representing two different parts of the compilation pipeline: the GeminiLogicalSimulator and the GeminiPhysicalSimulator. These two simulators take in different inputs (a logical circuit versus a physical circuit, respectively), and therefore have slightly different compilations.
# For postprocessingimport numpy as npfrom bloqade.cirq_utils.noise.model import GeminiOneZoneNoiseModel
# Defining dialects to program logical or physical kernels infrom bloqade import squinfrom bloqade.gemini import logical
# Constructing a logical or physical simulator and alternative simulation backendfrom bloqade.gemini.device import ( CliffTSimulatorBackend, GeminiLogicalSimulator, GeminiPhysicalSimulator, PPVMSimulatorBackend,)from bloqade.lanes.noise_model import generate_simple_noise_modelBasic Path for Constructing and Using a Logical Simulator
Section titled “Basic Path for Constructing and Using a Logical Simulator”Here, we provide a basic usage path of constructing and using a logical simulator. By default, the simulation backend is tsim.
# Construct a logical simulatorlogical_sim = GeminiLogicalSimulator()# Define a logical program to run on Gemini@logical.kernel(aggressive_unroll=True)def test_logical_program(): reg = squin.qalloc(5) squin.broadcast.x(reg) squin.cx(reg[0], reg[1]) return logical.terminal_measure(reg)# Compile the logical program to a tasklogical_task = logical_sim.task(test_logical_program)logical_result = logical_task.run(shots=1000)print(np.asarray(logical_result.measurements).shape)(1000, 35)Specifying an Alternative Simulation Backend
Section titled “Specifying an Alternative Simulation Backend”You can also specify an alternative simulation backend when constructing the simulator. For example, you can use the CliffTSimulatorBackend for CliffT integration.
To use
CliffTSimulatorBackend, you can runpip install "bloqade-lanes[clifft]".
# Create a logical simulator that uses CliffT as a simulator backendlogical_sim_clifft = GeminiLogicalSimulator(backend=CliffTSimulatorBackend())# Compile the program to a task and use CliffT to sample the results.logical_task_clifft = logical_sim_clifft.task(test_logical_program)logical_result_clifft = logical_task_clifft.run(shots=1000)print(np.asarray(logical_result_clifft.measurements).shape)(1000, 35)Using Physical Simulator and Configuring Simulator Backend
Section titled “Using Physical Simulator and Configuring Simulator Backend”You can analogously construct a GeminiPhysicalSimulator that compiles a physical squin kernel, and executes the task with a specified simulation backend.
# Construct a GeminiPhysicalSimulator that compiles a physical squin kernel and executes it.physical_sim = GeminiPhysicalSimulator()@squin.kernel()def test_physical_program(): reg = squin.qalloc(5) squin.broadcast.x(reg) squin.cx(reg[0], reg[1]) return squin.broadcast.measure(reg)physical_task = physical_sim.task(test_physical_program)physical_result = physical_task.run(shots=1000)print(np.asarray(physical_result.measurements).shape)(1000, 5)# You can alternatively construct a GeminiPhysicalSimulator with a different simulator backend, like CliffT.physical_sim_clifft = GeminiPhysicalSimulator(backend=CliffTSimulatorBackend())physical_task_clifft = physical_sim_clifft.task(test_physical_program)physical_result_clifft = physical_task_clifft.run(shots=1000)print(np.asarray(physical_result_clifft.measurements).shape)(1000, 5)You can also use our PPVM Simulation backend with a noise model that has atom loss, as shown below.
Note: the below values for loss are placeholders and may not reflect the loss parameters from the Gemini machine. You can customize these loss parameters to what you like.
noise_model_atom_loss = generate_simple_noise_model( GeminiOneZoneNoiseModel( local_loss_prob=0.001, local_unaddressed_loss_prob=0.001, global_loss_prob=0.001, cz_gate_loss_prob=0.001, cz_unpaired_loss_prob=0.001, move_loss_prob=0.0001, sit_loss_prob=0.0001, ))print(noise_model_atom_loss)SimpleNoiseModel(lane_noise=Method("lane_noise"), idle_noise=Method("idle_noise"), cz_unpaired_noise=Method("cz_unpaired_noise"), cz_paired_noise=Method("cz_paired_noise"), global_rz_noise=Method("global_rz_noise"), local_rz_noise=Method("local_rz_noise"), global_r_noise=Method("global_r_noise"), local_r_noise=Method("local_r_noise"), logical_initialize_clean=None, logical_initialize_noisy=None)simulator_with_loss = GeminiPhysicalSimulator( noise_model=noise_model_atom_loss, backend=PPVMSimulatorBackend())task_with_loss = simulator_with_loss.task(test_physical_program)result_with_loss = task_with_loss.run(shots=1000)