Simulators

Piquasso provides several built-in simulators for different photonic simulation tasks. The right choice depends on the representation you need, the instructions in your program, and whether you want finite-shot samples or the final state.

Gaussian simulator

Efficiently simulate Gaussian states, Gaussian gates, Gaussian channels, and compatible measurements.

Gaussian Simulator
Fock space-based simulators

Simulate states in the truncated Fock basis, including non-Gaussian operations such as Kerr-type gates.

Fock Simulators
Boson Sampling simulator

Sample from interferometer-based Boson Sampling circuits with terminal particle number measurements.

Boson Sampling Simulator

Choosing a simulator

GaussianSimulator

Use this for Gaussian circuits and efficient phase-space simulations based on first and second moments.

Gaussian Simulator
PureFockSimulator

Use this for pure-state simulations in a truncated Fock basis, including supported non-Gaussian operations.

Fock Simulators
FockSimulator

Use this when you need the more general Fock representation, for example for mixed states or supported noisy operations.

Fock Simulators
PassiveSimulator

Use this for Boson Sampling-style circuits with Fock-state inputs, interferometers, losses, and particle number measurements.

Boson Sampling Simulator

Quick examples

Gaussian simulation

Use the Gaussian simulator for circuits that can be represented in phase space.

import numpy as np
import piquasso as pq

with pq.Program() as program:
   pq.Q() | pq.Vacuum()
   pq.Q(0) | pq.Displacement(r=0.2)
   pq.Q(0, 1) | pq.Beamsplitter(theta=np.pi / 4)
   pq.Q(all) | pq.ParticleNumberMeasurement()

simulator = pq.GaussianSimulator(d=2)
result = simulator.execute(program, shots=10)

print(result.samples)

Fock simulation

Use a Fock simulator when the circuit contains non-Gaussian operations. The cutoff controls the size of the truncated Fock basis.

import numpy as np
import piquasso as pq

with pq.Program() as program:
   pq.Q() | pq.Vacuum()
   pq.Q(0) | pq.Displacement(r=0.4)
   pq.Q(0) | pq.Kerr(xi=0.05)

simulator = pq.PureFockSimulator(
   d=1,
   config=pq.Config(cutoff=8),
)
result = simulator.execute(program)

print(result.state.fock_probabilities)

Boson Sampling simulation

Use the Sampling simulator for particle-number input states followed by a linear optical circuit and terminal particle number measurements.

import numpy as np
import piquasso as pq

interferometer = np.array(
   [
      [1 / np.sqrt(2), 1 / np.sqrt(2)],
      [1 / np.sqrt(2), -1 / np.sqrt(2)],
   ]
)

with pq.Program() as program:
   pq.Q() | pq.NumberState([1, 1])
   pq.Q() | pq.Interferometer(interferometer)
   pq.Q(all) | pq.ParticleNumberMeasurement()

simulator = pq.PassiveSimulator(d=2)
result = simulator.execute(program, shots=10)

print(result.samples)

Automatic simulator selection with simulate

For small examples and quick experiments, the top-level pq.simulate function can choose a compatible built-in simulator for the program.

import numpy as np
import piquasso as pq

with pq.Program() as program:
   pq.Q() | pq.Vacuum()
   pq.Q(0) | pq.Displacement(r=0.2)
   pq.Q(0, 1) | pq.Beamsplitter(theta=np.pi / 4)
   pq.Q(all) | pq.ParticleNumberMeasurement()

result = pq.simulate(
   program,
   number_of_modes=2,
   shots=10,
)

print(result.samples)

The function accepts the same common simulation options as explicit simulator usage, including config, connector, and shots. Use an explicit simulator class when you want to document or control the exact representation used by the simulation.