Documentation
¶
Overview ¶
Package densitymatrix implements a density matrix quantum simulator supporting mixed states and noise channels.
The simulator represents the quantum state as a density matrix ρ (rho), a dim×dim Hermitian positive-semidefinite matrix with Tr(ρ) = 1, where dim = 2^n for n qubits.
Gate application uses the two-pass algorithm ρ' = U·ρ·U†. Noise channels use the Kraus representation ρ' = Σ_k E_k·ρ·E_k†.
Maximum practical size is ~14 qubits (4 GB for the density matrix).
Example (NoisyBell) ¶
package main
import (
"fmt"
"github.com/splch/goqu/circuit/builder"
"github.com/splch/goqu/sim/densitymatrix"
"github.com/splch/goqu/sim/noise"
)
func main() {
// Create a Bell circuit.
c, _ := builder.New("bell", 2).H(0).CNOT(0, 1).Build()
// Create a noise model with 1% depolarizing.
nm := noise.New()
nm.AddDefaultError(1, noise.Depolarizing1Q(0.01))
nm.AddDefaultError(2, noise.Depolarizing2Q(0.01))
// Simulate with noise.
dm := densitymatrix.New(2)
dm.WithNoise(nm)
dm.Evolve(c)
// Check purity (< 1 for mixed state).
p := dm.Purity()
fmt.Printf("Purity < 1: %v\n", p < 1.0-1e-10)
}
Output: Purity < 1: true
Example (PurityComparison) ¶
package main
import (
"fmt"
"math"
"github.com/splch/goqu/circuit/builder"
"github.com/splch/goqu/sim/densitymatrix"
"github.com/splch/goqu/sim/noise"
)
func main() {
c, _ := builder.New("h", 1).H(0).Build()
// Noiseless: purity = 1.
dm1 := densitymatrix.New(1)
dm1.Evolve(c)
fmt.Printf("Noiseless purity: %.4f\n", dm1.Purity())
// With noise: purity < 1.
nm := noise.New()
nm.AddDefaultError(1, noise.Depolarizing1Q(0.5))
dm2 := densitymatrix.New(1)
dm2.WithNoise(nm)
dm2.Evolve(c)
fmt.Printf("Noisy purity: %.4f\n", math.Round(dm2.Purity()*10000)/10000)
}
Output: Noiseless purity: 1.0000 Noisy purity: 0.5556
Index ¶
- type Sim
- func (s *Sim) Apply(c *ir.Circuit) error
- func (s *Sim) ApplyReadoutError(probs []float64) []float64
- func (s *Sim) Close() error
- func (s *Sim) DensityMatrix() []complex128
- func (s *Sim) DiagonalProbs() []float64
- func (s *Sim) Evolve(c *ir.Circuit) error
- func (s *Sim) ExpectPauliString(ps pauli.PauliString) float64
- func (s *Sim) ExpectPauliSum(ps pauli.PauliSum) float64
- func (s *Sim) ExpectationValue(qubits []int) float64
- func (s *Sim) Fidelity(pureState []complex128) float64
- func (s *Sim) Purity() float64
- func (s *Sim) Reset()
- func (s *Sim) Run(c *ir.Circuit, shots int) (map[string]int, error)
- func (s *Sim) RunDynamic(c *ir.Circuit, shots int) (map[string]int, error)
- func (s *Sim) WithNoise(nm *noise.NoiseModel) *Sim
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Sim ¶
type Sim struct {
// contains filtered or unexported fields
}
Sim simulates a circuit via density matrix evolution.
func (*Sim) Apply ¶ added in v1.2.0
Apply applies the circuit's gate operations to the current density matrix without resetting. Use this to compose circuits incrementally.
func (*Sim) ApplyReadoutError ¶
ApplyReadoutError applies per-qubit readout errors to probabilities. Each qubit's readout error independently flips the classical bit.
func (*Sim) DensityMatrix ¶
func (s *Sim) DensityMatrix() []complex128
DensityMatrix returns a copy of the current density matrix.
func (*Sim) DiagonalProbs ¶
DiagonalProbs returns the measurement probabilities (diagonal of ρ).
func (*Sim) Evolve ¶
Evolve resets the state to |0><0| and then applies the circuit's gate operations without measuring. To apply gates without resetting (e.g. to compose circuits incrementally), use Sim.Apply instead.
func (*Sim) ExpectPauliString ¶
func (s *Sim) ExpectPauliString(ps pauli.PauliString) float64
ExpectPauliString computes Re(Tr(ρ·P)) for a Pauli string P. For Hermitian observables (real coefficients), the imaginary part is zero. For non-Hermitian observables, use pauli.ExpectDM directly for complex128.
func (*Sim) ExpectPauliSum ¶
ExpectPauliSum computes Re(Tr(ρ·H)) for a Hamiltonian H (sum of Pauli strings). For Hermitian observables (real coefficients), the imaginary part is zero. For non-Hermitian observables, use pauli.ExpectSumDM directly for complex128.
func (*Sim) ExpectationValue ¶
ExpectationValue computes Tr(ρ·O) for a diagonal Pauli-Z observable specified as a list of qubit indices. For example, [0, 1] computes <Z0 Z1>. The result is rounded to 14 decimal places to clean up floating-point noise.
func (*Sim) Fidelity ¶
func (s *Sim) Fidelity(pureState []complex128) float64
Fidelity computes the fidelity F = ⟨ψ|ρ|ψ⟩ between a pure state |ψ⟩ and ρ.
func (*Sim) Reset ¶ added in v1.2.0
func (s *Sim) Reset()
Reset returns the density matrix to |0...0><0...0|.
func (*Sim) Run ¶
Run executes the circuit and returns measurement counts. For dynamic circuits (mid-circuit measurement, feed-forward, reset), it automatically uses per-shot simulation with state collapse.
func (*Sim) RunDynamic ¶
RunDynamic executes a dynamic circuit (mid-circuit measurement, feed-forward, reset) by simulating each shot independently with projective measurement and state collapse.