# Simulator: Introduction¶

In this example, we go through the basic features of the True-Q™ simulator. We begin by importing True-Q™ and instantiating a circuit to play with.

import trueq as tq
import matplotlib.pyplot as plt
import numpy as np

circuit = tq.Circuit([{0: tq.Gate.x, 1: tq.Gate.y}, {(0, 1): tq.Gate.cz}])
circuit.measure_all()

True-Q formatting will not be loaded without trusting this notebook or rerunning the affected cells. Notebooks can be marked as trusted by clicking "File -> Trust Notebook".
 Circuit Key: No key present in circuit. (0): Gate.x Name: Gate.x Aliases: Gate.x Gate.cliff1 Generators: 'X': 180.0 Matrix: 1.00 1.00 (1): Gate.y Name: Gate.y Aliases: Gate.y Gate.cliff2 Generators: 'Y': 180.0 Matrix: -1.00j 1.00j imm (0, 1): Gate.cz Name: Gate.cz Aliases: Gate.cz Likeness: CNOT Generators: 'IZ': 90.0 'ZI': 90.0 'ZZ': -90.0 Matrix: 1.00 1.00 1.00 -1.00 imm (0): Meas() Name: Meas() (1): Meas() Name: Meas()

## Simulator Basics¶

When we instantiate a new simulator object, it is always noiseless.

sim = tq.Simulator()


We can use it to simulate the final state of the circuit, with all initial states prepared as $|0\rangle$. Since the simulator is noiseless, the output state is a pure state; a noisy simulator will generally return a density matrix instead. If we want to force the output to be a density matrix, we can use sim0.state(circuit).upgrade().mat().

sim.state(circuit).mat()


Out:

array([0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j])


We can also use it to compute the overall action of the circuit. Since the simulator is currently noiseless, the output is a unitary matrix; a noisy simulator will return a superoperator (in the rowstacked basis).

tq.visualization.plot_mat(sim.operator(circuit).mat()) Finally, we can use a simulator to populate the results of the circuit. Currently, the simulator has no results:

circuit.results


Out:

Results({})


But after calling the run() method, it has results that are randomly sampled bitstrings from the final state of a state simulation. In this case all 100 shots end in the "11" state because the final state is a computational eigenstate.

sim.run(circuit, n_shots=100)
circuit.results


Out:

Results({'11': 100})


We construct a noisy simulator by appending noise sources to a noiseless simulator.

Simulation is cycle-based. Each noise source is called to add noise to the quantum state (or to the superoperator if operator() is called) for each cycle in a circuit. The order that noise sources are applied is dictated by the order in which they were added to the simulator.

# Add an overrotation noise, which causes single qubit gates to be simulated as U^1.02

# Add a depolarizing noise source at a rate of 0.8% per acted-on qubit per cycle

# Note that noisy simulators can be constructed as one-liners


Now when we ask for the final state, we get a density operator rather than a pure state:

tq.visualization.plot_mat(sim.state(circuit).mat()) And after calling the run() method (overwriting the results from above), we end up with noisy results:

sim.run(circuit, n_shots=100, overwrite=True)
circuit.results


Out:

Results({'01': 1, '11': 99})


We can also specify infinite shots to get the expectation values of each bitstring.

sim.run(circuit, n_shots=np.inf, overwrite=True)
circuit.results


Out:

Results({'00': 7.99041612947897e-05, '01': 0.008859008596685874, '10': 0.008859008596685874, '11': 0.9822020786453306})


## Restricting Noise to Certain Labels or Gates¶

Many of the noise sources have the options noisy_labels and noisy_gates which specify that only certain qubits or gates should recieve the noise source in question.

# initialize a simulator with different dephasing rates on the qubits
bitflip = lambda p: [np.sqrt(1 - p) * np.eye(2), np.sqrt(p) * np.fliplr(np.eye(2))]
sim0 = tq.Simulator()

# initialize a simulator that targets only a specific gate

# initialize a simulator that targets only specific gates on specific labels
sim2 = tq.Simulator()

# plot the final states
plt.figure(figsize=(10, 3))
tq.visualization.plot_mat(sim0.state(circuit).mat(), ax=plt.subplot("131"))
tq.visualization.plot_mat(sim1.state(circuit).mat(), ax=plt.subplot("132"))
tq.visualization.plot_mat(sim2.state(circuit).mat(), ax=plt.subplot("133")) Out:

Warning: Passing non-integers as three-element position specification is deprecated since 3.3 and will be removed two minor releases later.
(/home/user/jenkins/workspace/release trueq/docs/examples/simulation/intro.py:116)
Warning: Passing non-integers as three-element position specification is deprecated since 3.3 and will be removed two minor releases later.
(/home/user/jenkins/workspace/release trueq/docs/examples/simulation/intro.py:117)
Warning: Passing non-integers as three-element position specification is deprecated since 3.3 and will be removed two minor releases later.
(/home/user/jenkins/workspace/release trueq/docs/examples/simulation/intro.py:118)


Total running time of the script: ( 0 minutes 0.195 seconds)

Gallery generated by Sphinx-Gallery