or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

circuits.mddevices.mdindex.mdlinalg.mdops.mdprotocols.mdqis.mdremaining-modules.mdsim.mdstudy.mdtransformers.md

devices.mddocs/

0

# Devices and Noise Modeling

1

2

The devices module provides classes for modeling quantum hardware, qubits with different topologies, and realistic noise models for NISQ devices. This enables accurate simulation of quantum computations under realistic conditions.

3

4

## Qubit Types and Identifiers

5

6

### Qid - Base Quantum Identifier

7

8

Abstract base class for all quantum identifiers.

9

10

```python { .api }

11

class Qid:

12

"""Abstract base class for quantum identifiers."""

13

14

@property

15

@abc.abstractmethod

16

def dimension(self) -> int:

17

"""Dimension of the quantum system (2 for qubits, >2 for qudits)."""

18

19

def _comparison_key(self) -> Any:

20

"""Key used for comparison and hashing."""

21

22

def __lt__(self, other: 'Qid') -> bool:

23

"""Less than comparison for sorting."""

24

25

def validate_dimension(self, dimension: int) -> int:

26

"""Validate that this qid supports the given dimension."""

27

```

28

29

### GridQubit - 2D Grid Qubits

30

31

Qubits arranged in a 2D grid topology, commonly used for superconducting quantum processors.

32

33

```python { .api }

34

class GridQubit(Qid):

35

"""2D grid-based qubit (dimension 2)."""

36

37

def __init__(self, row: int, col: int) -> None:

38

"""Initialize a grid qubit at (row, col)."""

39

40

@property

41

def row(self) -> int:

42

"""Row coordinate of the qubit."""

43

44

@property

45

def col(self) -> int:

46

"""Column coordinate of the qubit."""

47

48

@property

49

def dimension(self) -> int:

50

"""Always returns 2 for qubits."""

51

52

@classmethod

53

def rect(cls, rows: int, cols: int) -> List['GridQubit']:

54

"""Create a rectangular array of grid qubits."""

55

56

@classmethod

57

def square(cls, length: int) -> List['GridQubit']:

58

"""Create a square array of grid qubits."""

59

60

def neighbors(self, *, diagonal: bool = True) -> Set['GridQubit']:

61

"""Get neighboring grid positions."""

62

63

def is_adjacent(self, other: 'GridQubit') -> bool:

64

"""Check if this qubit is adjacent to another."""

65

66

def __add__(self, other: Tuple[int, int]) -> 'GridQubit':

67

"""Add a (row, col) offset to this qubit."""

68

69

def __sub__(self, other: Tuple[int, int]) -> 'GridQubit':

70

"""Subtract a (row, col) offset from this qubit."""

71

```

72

73

### GridQid - Generalized Grid Qids

74

75

Generalized version of GridQubit supporting arbitrary dimensions.

76

77

```python { .api }

78

class GridQid(Qid):

79

"""Grid-based qubit identifier (generalized dimension)."""

80

81

def __init__(self, row: int, col: int, dimension: int) -> None:

82

"""Initialize a grid qid with specified dimension."""

83

84

@property

85

def row(self) -> int:

86

"""Row coordinate."""

87

88

@property

89

def col(self) -> int:

90

"""Column coordinate."""

91

92

@property

93

def dimension(self) -> int:

94

"""Dimension of the quantum system."""

95

96

def neighbors(self, *, diagonal: bool = True) -> Set['GridQid']:

97

"""Get neighboring grid positions with same dimension."""

98

```

99

100

### LineQubit - 1D Linear Qubits

101

102

Qubits arranged in a linear topology.

103

104

```python { .api }

105

class LineQubit(Qid):

106

"""1D line-based qubit (dimension 2)."""

107

108

def __init__(self, x: int) -> None:

109

"""Initialize a line qubit at position x."""

110

111

@property

112

def x(self) -> int:

113

"""Position along the line."""

114

115

@property

116

def dimension(self) -> int:

117

"""Always returns 2 for qubits."""

118

119

@classmethod

120

def range(cls, *args) -> List['LineQubit']:

121

"""Create a range of line qubits.

122

123

Args:

124

*args: Either range(stop) or range(start, stop) or range(start, stop, step)

125

"""

126

127

def neighbors(self, radius: int = 1) -> Set['LineQubit']:

128

"""Get neighboring positions within given radius."""

129

130

def is_adjacent(self, other: 'LineQubit') -> bool:

131

"""Check if this qubit is adjacent to another."""

132

```

133

134

### LineQid - Generalized Line Qids

135

136

Generalized version of LineQubit supporting arbitrary dimensions.

137

138

```python { .api }

139

class LineQid(Qid):

140

"""Line-based qubit identifier (generalized dimension)."""

141

142

def __init__(self, x: int, dimension: int) -> None:

143

"""Initialize a line qid with specified dimension."""

144

145

@property

146

def x(self) -> int:

147

"""Position along the line."""

148

149

@property

150

def dimension(self) -> int:

151

"""Dimension of the quantum system."""

152

```

153

154

## Device Classes

155

156

### Device - Abstract Base Class

157

158

Base class for modeling quantum devices with hardware constraints.

159

160

```python { .api }

161

class Device:

162

"""Abstract base class for quantum devices."""

163

164

@abc.abstractmethod

165

def qubits(self) -> FrozenSet[Qid]:

166

"""Qubits available on this device."""

167

168

def qubit_set(self) -> FrozenSet[Qid]:

169

"""Alias for qubits()."""

170

171

def decompose_operation(self, operation: 'cirq.Operation') -> 'cirq.OP_TREE':

172

"""Decompose an operation into device-native operations."""

173

174

def validate_operation(self, operation: 'cirq.Operation') -> None:

175

"""Validate that an operation can be performed on this device."""

176

177

def validate_circuit(self, circuit: 'cirq.AbstractCircuit') -> None:

178

"""Validate that a circuit can be run on this device."""

179

180

def validate_moment(self, moment: 'cirq.Moment') -> None:

181

"""Validate that a moment can be performed on this device."""

182

183

def can_add_operation_into_moment(self, operation: 'cirq.Operation', moment: 'cirq.Moment') -> bool:

184

"""Check if an operation can be added to a moment."""

185

186

def duration_of(self, operation: 'cirq.Operation') -> 'cirq.Duration':

187

"""Get the duration of an operation on this device."""

188

```

189

190

### DeviceMetadata

191

192

Metadata describing device capabilities and constraints.

193

194

```python { .api }

195

class DeviceMetadata:

196

"""Metadata describing device capabilities."""

197

198

def __init__(self, qubits: Iterable[Qid],

199

pairs: Iterable[Tuple[Qid, Qid]]) -> None:

200

"""Initialize device metadata."""

201

202

@property

203

def qubits(self) -> FrozenSet[Qid]:

204

"""Set of qubits on the device."""

205

206

@property

207

def qubit_pairs(self) -> FrozenSet[Tuple[Qid, Qid]]:

208

"""Set of two-qubit gate pairs."""

209

210

def neighbors_of(self, qubit: Qid) -> Set[Qid]:

211

"""Get neighboring qubits that can interact with the given qubit."""

212

213

def isolated_qubits(self) -> FrozenSet[Qid]:

214

"""Qubits that cannot interact with any other qubits."""

215

```

216

217

### GridDeviceMetadata

218

219

Specialized metadata for grid-based quantum devices.

220

221

```python { .api }

222

class GridDeviceMetadata(DeviceMetadata):

223

"""Metadata for grid-based quantum devices."""

224

225

def __init__(self, qubit_pairs: Iterable[Tuple[GridQubit, GridQubit]],

226

gateset: Optional['cirq.Gateset'] = None) -> None:

227

"""Initialize grid device metadata."""

228

229

@classmethod

230

def square(cls, length: int, **kwargs) -> 'GridDeviceMetadata':

231

"""Create metadata for a square grid device."""

232

233

@classmethod

234

def rect(cls, rows: int, cols: int, **kwargs) -> 'GridDeviceMetadata':

235

"""Create metadata for a rectangular grid device."""

236

```

237

238

### UNCONSTRAINED_DEVICE

239

240

A device with no constraints that accepts any operation.

241

242

```python { .api }

243

UNCONSTRAINED_DEVICE: Device

244

"""Device with no constraints - accepts any quantum operation."""

245

```

246

247

## Noise Models

248

249

### NoiseModel - Abstract Base Class

250

251

Base class for modeling quantum noise.

252

253

```python { .api }

254

class NoiseModel:

255

"""Abstract base class for noise models."""

256

257

@abc.abstractmethod

258

def noisy_operation(self, operation: 'cirq.Operation') -> 'cirq.OP_TREE':

259

"""Apply noise to an operation, returning noisy operations."""

260

261

def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence[Qid]) -> 'cirq.OP_TREE':

262

"""Apply noise to all operations in a moment."""

263

264

def noisy_moments(self, moments: Sequence['cirq.Moment'], system_qubits: Sequence[Qid]) -> Sequence['cirq.OP_TREE']:

265

"""Apply noise to a sequence of moments."""

266

267

def is_virtual_moment(self, moment: 'cirq.Moment') -> bool:

268

"""Check if a moment should be treated as virtual (no duration)."""

269

```

270

271

### ConstantQubitNoiseModel

272

273

Noise model with constant per-qubit noise rates.

274

275

```python { .api }

276

class ConstantQubitNoiseModel(NoiseModel):

277

"""Noise model with constant per-qubit noise."""

278

279

def __init__(self, qubit_noise_gate: 'cirq.Gate') -> None:

280

"""Initialize with a noise gate applied to each qubit."""

281

282

def noisy_operation(self, operation: 'cirq.Operation') -> 'cirq.OP_TREE':

283

"""Add qubit noise after the operation."""

284

```

285

286

### NoiseModelFromNoiseProperties

287

288

Noise model derived from detailed noise characterization.

289

290

```python { .api }

291

class NoiseModelFromNoiseProperties(NoiseModel):

292

"""Noise model derived from noise properties."""

293

294

def __init__(self, noise_properties: 'NoiseProperties') -> None:

295

"""Initialize from noise properties characterization."""

296

297

def noisy_operation(self, operation: 'cirq.Operation') -> 'cirq.OP_TREE':

298

"""Apply noise based on operation type and noise properties."""

299

```

300

301

### InsertionNoiseModel

302

303

Noise model that inserts noise operations at specified locations.

304

305

```python { .api }

306

class InsertionNoiseModel(NoiseModel):

307

"""Noise model that inserts noise operations."""

308

309

def __init__(self, ops_added: Dict[OpIdentifier, 'cirq.OP_TREE']) -> None:

310

"""Initialize with operations to add for each gate type."""

311

312

def noisy_operation(self, operation: 'cirq.Operation') -> 'cirq.OP_TREE':

313

"""Insert additional noise operations."""

314

```

315

316

### ThermalNoiseModel

317

318

Thermal noise model for quantum operations.

319

320

```python { .api }

321

class ThermalNoiseModel(NoiseModel):

322

"""Thermal noise model for quantum operations."""

323

324

def __init__(self, frozen_pi_hats: Dict['cirq.Qid', np.ndarray],

325

decay_constants: Dict['cirq.Qid', float],

326

gate_times: Dict[type, 'cirq.Duration']) -> None:

327

"""Initialize thermal noise model."""

328

329

def noisy_operation(self, operation: 'cirq.Operation') -> 'cirq.OP_TREE':

330

"""Apply thermal noise during gate operation."""

331

```

332

333

## Noise Properties

334

335

### NoiseProperties

336

337

Properties characterizing noise in quantum operations.

338

339

```python { .api }

340

class NoiseProperties:

341

"""Properties characterizing noise in quantum operations."""

342

343

def __init__(self,

344

gate_times_ns: Dict[type, float],

345

t1_ns: Dict['cirq.Qid', float],

346

t2_ns: Dict['cirq.Qid', float],

347

readout_errors: Dict['cirq.Qid', Tuple[float, float]],

348

gate_pauli_errors: Dict['cirq.Qid', Dict[type, float]]) -> None:

349

"""Initialize noise properties."""

350

351

@property

352

def gate_times_ns(self) -> Dict[type, float]:

353

"""Gate execution times in nanoseconds."""

354

355

@property

356

def t1_ns(self) -> Dict['cirq.Qid', float]:

357

"""T1 coherence times in nanoseconds."""

358

359

@property

360

def t2_ns(self) -> Dict['cirq.Qid', float]:

361

"""T2 dephasing times in nanoseconds."""

362

363

@property

364

def readout_errors(self) -> Dict['cirq.Qid', Tuple[float, float]]:

365

"""Readout error probabilities (p01, p10)."""

366

367

@property

368

def gate_pauli_errors(self) -> Dict['cirq.Qid', Dict[type, float]]:

369

"""Pauli error rates for different gate types."""

370

```

371

372

### SuperconductingQubitsNoiseProperties

373

374

Specialized noise properties for superconducting qubits.

375

376

```python { .api }

377

class SuperconductingQubitsNoiseProperties(NoiseProperties):

378

"""Noise properties for superconducting qubits."""

379

380

def __init__(self,

381

t1_ns: Dict['cirq.Qid', float],

382

tphi_ns: Dict['cirq.Qid', float],

383

readout_errors: Dict['cirq.Qid', Tuple[float, float]],

384

gate_pauli_errors: Dict['cirq.Qid', Dict[type, float]] = None) -> None:

385

"""Initialize superconducting qubit noise properties."""

386

387

@classmethod

388

def from_default_noise_model(cls, qubits: Iterable['cirq.Qid']) -> 'SuperconductingQubitsNoiseProperties':

389

"""Create default noise model for superconducting qubits."""

390

```

391

392

### OpIdentifier

393

394

Identifier for operations in noise models.

395

396

```python { .api }

397

class OpIdentifier:

398

"""Identifier for operations in noise models."""

399

400

def __init__(self, gate_type: type, *qubits: 'cirq.Qid') -> None:

401

"""Initialize operation identifier."""

402

403

@property

404

def gate_type(self) -> type:

405

"""Type of the gate."""

406

407

@property

408

def qubits(self) -> Tuple['cirq.Qid', ...]:

409

"""Qubits the operation acts on."""

410

```

411

412

## Device Topologies

413

414

### NamedTopology

415

416

Abstract base class for named device topologies.

417

418

```python { .api }

419

class NamedTopology:

420

"""Abstract base class for named device topologies."""

421

422

@abc.abstractmethod

423

def nodes(self) -> Set[Any]:

424

"""Nodes in the topology."""

425

426

@abc.abstractmethod

427

def edges(self) -> Set[Tuple[Any, Any]]:

428

"""Edges in the topology."""

429

430

def neighbors_of(self, node: Any) -> Set[Any]:

431

"""Get neighbors of a node."""

432

```

433

434

### LineTopology

435

436

Linear arrangement of qubits.

437

438

```python { .api }

439

class LineTopology(NamedTopology):

440

"""Linear arrangement of qubits."""

441

442

def __init__(self, length: int) -> None:

443

"""Initialize line topology with given length."""

444

445

def nodes(self) -> Set[int]:

446

"""Node indices in the line."""

447

448

def edges(self) -> Set[Tuple[int, int]]:

449

"""Adjacent pairs in the line."""

450

```

451

452

### TiltedSquareLattice

453

454

Tilted square lattice topology.

455

456

```python { .api }

457

class TiltedSquareLattice(NamedTopology):

458

"""Tilted square lattice topology."""

459

460

def __init__(self, rows: int, cols: int) -> None:

461

"""Initialize tilted square lattice."""

462

463

def nodes(self) -> Set[Tuple[int, int]]:

464

"""Grid positions in the lattice."""

465

466

def edges(self) -> Set[Tuple[Tuple[int, int], Tuple[int, int]]]:

467

"""Connected pairs in the lattice."""

468

```

469

470

## Noise Constants and Utilities

471

472

```python { .api }

473

NO_NOISE: NoiseModel

474

"""No-noise model constant."""

475

476

NOISE_MODEL_LIKE = Union[NoiseModel, 'cirq.Gate', Callable[['cirq.Operation'], 'cirq.OP_TREE']]

477

"""Type hint for noise model-like objects."""

478

```

479

480

## Utility Functions

481

482

### Device Layout Visualization

483

484

```python { .api }

485

def draw_gridlike(qubits: Iterable[GridQubit],

486

ax: Optional['matplotlib.axes.Axes'] = None,

487

tilted: bool = True) -> 'matplotlib.axes.Axes':

488

"""Draw grid-like device layout."""

489

```

490

491

### Placement Functions

492

493

```python { .api }

494

def get_placements(topology: NamedTopology,

495

circuit_qubits: Sequence['cirq.Qid']) -> List[Dict['cirq.Qid', Any]]:

496

"""Get valid qubit placements on topology."""

497

498

def is_valid_placement(topology: NamedTopology,

499

qubit_mapping: Dict['cirq.Qid', Any]) -> bool:

500

"""Check if qubit placement is valid."""

501

502

def draw_placements(topology: NamedTopology,

503

qubit_mapping: Dict['cirq.Qid', Any]) -> None:

504

"""Visualize qubit placements."""

505

```

506

507

### Noise Conversion Functions

508

509

```python { .api }

510

def decay_constant_to_xeb_fidelity(decay_constant: float, num_qubits: int) -> float:

511

"""Convert decay constant to XEB fidelity."""

512

513

def decay_constant_to_pauli_error(decay_constant: float) -> float:

514

"""Convert decay constant to Pauli error."""

515

516

def pauli_error_to_decay_constant(pauli_error: float) -> float:

517

"""Convert Pauli error to decay constant."""

518

519

def xeb_fidelity_to_decay_constant(xeb_fidelity: float, num_qubits: int) -> float:

520

"""Convert XEB fidelity to decay constant."""

521

522

def pauli_error_from_t1(t1: float, gate_time: float) -> float:

523

"""Calculate Pauli error from T1 time."""

524

525

def average_error(errors: Iterable[float]) -> float:

526

"""Calculate average error rate."""

527

528

def decoherence_pauli_error(t1: float, t2: float, gate_time: float) -> float:

529

"""Calculate decoherence Pauli error."""

530

```

531

532

## Usage Examples

533

534

### Creating and Using Qubits

535

536

```python

537

import cirq

538

539

# Line qubits for 1D topologies

540

line_qubits = cirq.LineQubit.range(5)

541

print(f"Line qubits: {line_qubits}")

542

543

# Grid qubits for 2D topologies

544

grid_qubits = cirq.GridQubit.rect(3, 3)

545

print(f"Grid qubits: {grid_qubits}")

546

547

# Check adjacency

548

q0, q1 = cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)

549

print(f"Adjacent: {q0.is_adjacent(q1)}")

550

print(f"Neighbors of {q0}: {q0.neighbors()}")

551

```

552

553

### Applying Noise Models

554

555

```python

556

import cirq

557

558

# Create a simple circuit

559

qubits = cirq.LineQubit.range(2)

560

circuit = cirq.Circuit([

561

cirq.H(qubits[0]),

562

cirq.CNOT(qubits[0], qubits[1])

563

])

564

565

# Apply depolarizing noise

566

noise_model = cirq.ConstantQubitNoiseModel(cirq.depolarize(p=0.01))

567

noisy_circuit = circuit.with_noise(noise_model)

568

569

print("Original circuit:")

570

print(circuit)

571

print("\nNoisy circuit:")

572

print(noisy_circuit)

573

```

574

575

### Custom Device Definition

576

577

```python

578

import cirq

579

580

class MyDevice(cirq.Device):

581

def __init__(self, qubits):

582

self._qubits = frozenset(qubits)

583

584

def qubits(self):

585

return self._qubits

586

587

def validate_operation(self, operation):

588

if not set(operation.qubits).issubset(self._qubits):

589

raise ValueError(f"Operation {operation} uses invalid qubits")

590

# Add custom validation logic here

591

592

# Create device and validate circuit

593

qubits = cirq.LineQubit.range(3)

594

device = MyDevice(qubits)

595

circuit = cirq.Circuit(cirq.H(qubits[0]))

596

597

try:

598

device.validate_circuit(circuit)

599

print("Circuit is valid for device")

600

except ValueError as e:

601

print(f"Invalid circuit: {e}")

602

```

603

604

This documentation provides comprehensive coverage of device modeling and noise simulation capabilities in Cirq for realistic NISQ quantum computing.