or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

circuit-construction.mdcircuit-formats.mdgates-operations.mdindex.mdprimitives.mdproviders.mdquantum-information.mdsynthesis.mdtranspilation.mdvisualization.md

primitives.mddocs/

0

# Quantum Primitives

1

2

Qiskit's primitives provide the modern interface for quantum computation using the V2 interface. They offer two core computational primitives: StatevectorSampler for circuit execution and measurement, and StatevectorEstimator for expectation value calculation. This interface uses Primitive Unified Blocs (PUBs) for efficient vectorized computation.

3

4

## Capabilities

5

6

### Sampler V2 Primitive

7

8

The StatevectorSampler primitive executes quantum circuits and returns measurement samples, providing the foundation for sampling-based quantum algorithms.

9

10

```python { .api }

11

class StatevectorSampler(BaseSamplerV2):

12

def __init__(self, *, default_shots=1024, seed=None):

13

"""

14

Initialize StatevectorSampler primitive (V2 interface).

15

16

Parameters:

17

- default_shots: Default number of measurement shots

18

- seed: Random seed for reproducible results

19

"""

20

21

def run(self, pubs, *, shots=None):

22

"""

23

Execute primitive unified blocs (PUBs) and return measurement results.

24

25

Parameters:

26

- pubs: Primitive unified blocs - list of (circuit, parameter_values, shots) tuples

27

- shots: Default shots for all PUBs (overridden by per-PUB shots)

28

29

Returns:

30

PrimitiveJob: Job object with result() method

31

"""

32

33

class BackendSamplerV2(BaseSamplerV2):

34

def __init__(self, backend, *, default_shots=1024, seed=None):

35

"""

36

Backend-based Sampler V2 implementation.

37

38

Parameters:

39

- backend: Quantum backend to execute circuits on

40

- default_shots: Default number of shots

41

- seed: Random seed

42

"""

43

44

def run(self, pubs, *, shots=None):

45

"""Execute PUBs on backend."""

46

47

@property

48

def backend(self):

49

"""Backend used for execution."""

50

51

@property

52

def options(self):

53

"""Execution options."""

54

55

class SamplerPubResult(PubResult):

56

"""Result for a single PUB execution in sampler."""

57

58

@property

59

def data(self):

60

"""

61

Measurement data as DataBin with register-named BitArrays.

62

Access measurement outcomes via register names (e.g., result.data.c for register 'c').

63

"""

64

65

@property

66

def metadata(self):

67

"""PUB execution metadata."""

68

```

69

70

### Estimator V2 Primitive

71

72

The StatevectorEstimator primitive calculates expectation values of observables on quantum states, essential for variational quantum algorithms and quantum chemistry.

73

74

```python { .api }

75

class StatevectorEstimator(BaseEstimatorV2):

76

def __init__(self, *, default_precision=0.015625, seed=None):

77

"""

78

Initialize StatevectorEstimator primitive (V2 interface).

79

80

Parameters:

81

- default_precision: Default precision for expectation values

82

- seed: Random seed for reproducible results

83

"""

84

85

def run(self, pubs, *, precision=None):

86

"""

87

Calculate expectation values for primitive unified blocs.

88

89

Parameters:

90

- pubs: List of (circuit, observables, parameter_values) tuples

91

- precision: Target precision for expectation values

92

93

Returns:

94

PrimitiveJob: Job object with result() method

95

"""

96

97

class BackendEstimatorV2(BaseEstimatorV2):

98

def __init__(self, backend, *, default_precision=0.015625, seed=None):

99

"""

100

Backend-based Estimator V2 implementation.

101

102

Parameters:

103

- backend: Quantum backend to execute circuits on

104

- default_precision: Default precision

105

- seed: Random seed

106

"""

107

108

def run(self, pubs, *, precision=None):

109

"""Calculate expectation values on backend."""

110

111

@property

112

def backend(self):

113

"""Backend used for execution."""

114

115

@property

116

def options(self):

117

"""Execution options."""

118

119

class EstimatorPubResult(PubResult):

120

"""Result for a single PUB execution in estimator."""

121

122

@property

123

def data(self):

124

"""

125

Expectation value data as DataBin with evs array.

126

Access expectation values via result.data.evs.

127

"""

128

129

@property

130

def metadata(self):

131

"""PUB calculation metadata."""

132

```

133

134

### Base Classes

135

136

Abstract base classes defining the V2 primitive interfaces.

137

138

```python { .api }

139

class BaseSamplerV2:

140

"""Abstract base class for V2 Sampler implementations."""

141

142

def run(self, pubs, *, shots=None):

143

"""Run primitive unified blocs and return measurement results."""

144

raise NotImplementedError

145

146

class BaseEstimatorV2:

147

"""Abstract base class for V2 Estimator implementations."""

148

149

def run(self, pubs, *, precision=None):

150

"""Calculate expectation values for primitive unified blocs."""

151

raise NotImplementedError

152

```

153

154

### Primitive Jobs and Results

155

156

Job management and result handling for primitive execution.

157

158

```python { .api }

159

class PrimitiveJob(BasePrimitiveJob):

160

"""Job object returned by primitive run() methods."""

161

162

def result(self):

163

"""

164

Get job result (blocking).

165

166

Returns:

167

PrimitiveResult: Execution results containing list of PubResults

168

"""

169

170

def status(self):

171

"""Get job status."""

172

173

def cancel(self):

174

"""Cancel the job if possible."""

175

176

def running(self):

177

"""Check if job is currently running."""

178

179

def done(self):

180

"""Check if job is completed."""

181

182

class PrimitiveResult:

183

"""Result from V2 primitive execution containing multiple PubResults."""

184

185

def __getitem__(self, index):

186

"""Access individual PubResult by index."""

187

188

def __len__(self):

189

"""Number of PubResults."""

190

191

def __iter__(self):

192

"""Iterate over PubResults."""

193

194

class PubResult:

195

"""Base class for primitive unified bloc results."""

196

197

@property

198

def data(self):

199

"""Result data as DataBin."""

200

201

@property

202

def metadata(self):

203

"""Result metadata."""

204

```

205

206

### Container Classes

207

208

Data structures for handling primitive inputs and outputs with V2 interface.

209

210

```python { .api }

211

class BitArray:

212

"""Efficient storage of measurement bit arrays organized by classical register."""

213

214

def __init__(self, array, num_bits, shape=None):

215

"""

216

Initialize bit array.

217

218

Parameters:

219

- array: Array of measurement outcomes

220

- num_bits: Number of bits per measurement

221

- shape: Shape of measurement array

222

"""

223

224

def get_counts(self, loc=None):

225

"""

226

Get measurement counts dictionary.

227

228

Parameters:

229

- loc: Specific bit locations to count

230

231

Returns:

232

dict: Counts dictionary mapping bitstrings to frequencies

233

"""

234

235

def get_bitstrings(self, loc=None):

236

"""Get measurement results as bit strings."""

237

238

def slice_bits(self, indices):

239

"""Extract specific bit positions."""

240

241

@property

242

def shape(self):

243

"""Shape of the bit array."""

244

245

@property

246

def num_bits(self):

247

"""Number of bits per measurement."""

248

249

@property

250

def num_shots(self):

251

"""Number of measurement shots."""

252

253

class DataBin:

254

"""Container for primitive execution data with register-based access."""

255

256

def __init__(self, **data):

257

"""Initialize data container with named data fields."""

258

259

def __getattr__(self, name):

260

"""Access data fields as attributes (e.g., data.c for register 'c')."""

261

262

def __getitem__(self, key):

263

"""Access data fields by key."""

264

265

def keys(self):

266

"""Get data field names."""

267

268

def values(self):

269

"""Get data field values."""

270

271

def items(self):

272

"""Get (name, value) pairs."""

273

```

274

275

### Primitive Unified Blocs (PUBs)

276

277

Input specification format for V2 primitives enabling vectorized computation.

278

279

```python { .api }

280

# Type aliases for PUB specifications

281

SamplerPubLike = Union[

282

QuantumCircuit, # Simple circuit

283

Tuple[QuantumCircuit, ArrayLike], # Circuit with parameter values

284

Tuple[QuantumCircuit, ArrayLike, int], # Circuit with parameters and shots

285

]

286

287

EstimatorPubLike = Union[

288

Tuple[QuantumCircuit, ObservablesArrayLike], # Circuit and observables

289

Tuple[QuantumCircuit, ObservablesArrayLike, ArrayLike], # With parameter values

290

]

291

292

ObservablesArrayLike = Union[

293

str, # Pauli string

294

SparsePauliOp, # Sparse Pauli operator

295

List[Union[str, SparsePauliOp]], # List of observables

296

]

297

298

BindingsArrayLike = Union[

299

Mapping[Parameter, float], # Single parameter binding

300

Sequence[Mapping[Parameter, float]], # Multiple parameter sets

301

ArrayLike, # Array of parameter values

302

]

303

```

304

305

### Usage Examples

306

307

```python

308

from qiskit.primitives import StatevectorSampler, StatevectorEstimator

309

from qiskit import QuantumCircuit, Parameter

310

from qiskit.quantum_info import SparsePauliOp

311

import numpy as np

312

313

# Basic V2 Sampler usage

314

circuit = QuantumCircuit(2, 2, name='bell')

315

circuit.h(0)

316

circuit.cx(0, 1)

317

circuit.measure_all()

318

319

sampler = StatevectorSampler()

320

job = sampler.run([circuit], shots=1000)

321

result = job.result()

322

pub_result = result[0] # First (and only) PUB result

323

324

# Access measurement data by register name

325

counts = pub_result.data.c.get_counts() # 'c' is the classical register name

326

print(f"Measurement counts: {counts}")

327

328

# Parameterized circuit with V2 interface (PUB format)

329

theta = Parameter('θ')

330

param_circuit = QuantumCircuit(1, 1)

331

param_circuit.ry(theta, 0)

332

param_circuit.measure_all()

333

334

# Run with multiple parameter values using PUB format

335

angles = [[0], [np.pi/4], [np.pi/2], [np.pi]]

336

job = sampler.run([(param_circuit, angles)], shots=1024)

337

result = job.result()

338

339

# Access results for different parameter values

340

param_result = result[0]

341

measurement_data = param_result.data.c # BitArray with shape matching parameter array

342

for i, angle in enumerate([0, np.pi/4, np.pi/2, np.pi]):

343

counts = measurement_data.get_counts(i) # Get counts for i-th parameter set

344

print(f"θ = {angle:.2f}: {counts}")

345

346

# V2 Estimator usage with PUB format

347

observable = SparsePauliOp.from_list([('ZZ', 1.0), ('XX', 0.5)])

348

prep_circuit = QuantumCircuit(2)

349

prep_circuit.h(0)

350

prep_circuit.cx(0, 1) # Bell state preparation

351

352

estimator = StatevectorEstimator()

353

job = estimator.run([(prep_circuit, observable)])

354

result = job.result()

355

expectation_value = result[0].data.evs[0] # Access expectation values via .evs

356

print(f"Expectation value: {expectation_value}")

357

358

# Vectorized estimator computation

359

multiple_observables = [

360

SparsePauliOp.from_list([('ZZ', 1.0)]),

361

SparsePauliOp.from_list([('XX', 1.0)]),

362

SparsePauliOp.from_list([('YY', 1.0)])

363

]

364

365

# Single PUB with multiple observables (vectorized)

366

job = estimator.run([(prep_circuit, multiple_observables)], precision=0.01)

367

result = job.result()

368

expectation_values = result[0].data.evs # Array of expectation values

369

print(f"Multiple expectations: {expectation_values}")

370

371

# Variational algorithm example with V2 primitives

372

def ansatz_circuit(params):

373

circuit = QuantumCircuit(2)

374

circuit.ry(params[0], 0)

375

circuit.ry(params[1], 1)

376

circuit.cx(0, 1)

377

circuit.ry(params[2], 0)

378

circuit.ry(params[3], 1)

379

return circuit

380

381

# Hamiltonian for optimization

382

hamiltonian = SparsePauliOp.from_list([

383

('ZZ', 1.0),

384

('XX', 0.5),

385

('YY', 0.5),

386

('ZI', -0.1),

387

('IZ', -0.1)

388

])

389

390

# Multiple parameter sets in a single PUB for efficiency

391

param_sets = [

392

[0, 0, 0, 0],

393

[np.pi/4, np.pi/4, np.pi/4, np.pi/4],

394

[np.pi/2, 0, np.pi/2, 0]

395

]

396

397

ansatz = ansatz_circuit([Parameter(f'θ{i}') for i in range(4)])

398

job = estimator.run([(ansatz, hamiltonian, param_sets)])

399

result = job.result()

400

401

# Access energy values for all parameter sets at once

402

energies = result[0].data.evs

403

for i, params in enumerate(param_sets):

404

print(f"Parameters {params}: Energy = {energies[i]:.4f}")

405

406

# Backend execution with V2 primitives

407

from qiskit.primitives import BackendSamplerV2, BackendEstimatorV2

408

from qiskit.providers.fake_provider import FakeManila

409

410

backend = FakeManila()

411

backend_sampler = BackendSamplerV2(backend)

412

413

# V2 backend execution

414

job = backend_sampler.run([circuit], shots=2048)

415

result = job.result()

416

backend_counts = result[0].data.c.get_counts()

417

print(f"Backend execution result: {backend_counts}")

418

```