@@ -56,7 +56,75 @@ void bindNoiseModel(py::module &mod) {
56
56
mod, " NoiseModel" ,
57
57
" The `NoiseModel` defines a set of :class:`KrausChannel`'s applied to "
58
58
" specific qubits after the invocation of specified quantum operations." )
59
- .def (py::init<>(), " Construct an empty noise model." )
59
+ .def (py::init<>([mod]() {
60
+ // Create the noise model
61
+ auto model = std::make_unique<noise_model>();
62
+
63
+ // Define a map of channel names to generator functions
64
+ static std::map<std::string, std::function<kraus_channel (
65
+ const std::vector<double > &)>>
66
+ channelGenerators = {
67
+ {" DepolarizationChannel" ,
68
+ [](const std::vector<double > &p) -> kraus_channel {
69
+ return depolarization_channel (p);
70
+ }},
71
+ {" AmplitudeDampingChannel" ,
72
+ [](const std::vector<double > &p) -> kraus_channel {
73
+ return amplitude_damping_channel (p);
74
+ }},
75
+ {" BitFlipChannel" ,
76
+ [](const std::vector<double > &p) -> kraus_channel {
77
+ return bit_flip_channel (p);
78
+ }},
79
+ {" PhaseFlipChannel" ,
80
+ [](const std::vector<double > &p) -> kraus_channel {
81
+ return phase_flip_channel (p);
82
+ }},
83
+ {" XError" ,
84
+ [](const std::vector<double > &p) -> kraus_channel {
85
+ return x_error (p);
86
+ }},
87
+ {" YError" ,
88
+ [](const std::vector<double > &p) -> kraus_channel {
89
+ return y_error (p);
90
+ }},
91
+ {" ZError" ,
92
+ [](const std::vector<double > &p) -> kraus_channel {
93
+ return z_error (p);
94
+ }},
95
+ {" PhaseDamping" ,
96
+ [](const std::vector<double > &p) -> kraus_channel {
97
+ return phase_damping (p);
98
+ }},
99
+ {" Pauli1" ,
100
+ [](const std::vector<double > &p) -> kraus_channel {
101
+ return pauli1 (p);
102
+ }},
103
+ {" Pauli2" ,
104
+ [](const std::vector<double > &p) -> kraus_channel {
105
+ return pauli2 (p);
106
+ }},
107
+ {" Depolarization1" ,
108
+ [](const std::vector<double > &p) -> kraus_channel {
109
+ return depolarization1 (p);
110
+ }},
111
+ {" Depolarization2" ,
112
+ [](const std::vector<double > &p) -> kraus_channel {
113
+ return depolarization2 (p);
114
+ }}};
115
+
116
+ // Register each channel generator
117
+ for (const auto &[name, generator] : channelGenerators) {
118
+ if (py::hasattr (mod, name.c_str ())) {
119
+ py::type channelType = py::getattr (mod, name.c_str ());
120
+ auto key = py::hash (channelType);
121
+ model->register_channel (key, generator);
122
+ }
123
+ }
124
+
125
+ return model;
126
+ }),
127
+ " Construct a noise model with all built-in channels pre-registered." )
60
128
.def (
61
129
" register_channel" ,
62
130
[](noise_model &self, const py::type krausT) {
@@ -234,9 +302,13 @@ void bindNoiseChannels(py::module &mod) {
234
302
For `probability = 0.0`, the channel will behave noise-free.
235
303
For `probability = 0.75`, the channel will fully depolarize the state.
236
304
For `probability = 1.0`, the channel will be uniform.)#" )
305
+ .def (py::init<std::vector<double >>())
237
306
.def (py::init<double >(), py::arg (" probability" ),
238
307
" Initialize the `DepolarizationChannel` with the provided "
239
- " `probability`." );
308
+ " `probability`." )
309
+ .def_readonly_static (
310
+ " num_parameters" , &depolarization_channel::num_parameters,
311
+ " The number of parameters this channel requires at construction." );
240
312
241
313
py::class_<amplitude_damping_channel, kraus_channel>(
242
314
mod, " AmplitudeDampingChannel" ,
@@ -253,9 +325,13 @@ void bindNoiseChannels(py::module &mod) {
253
325
representing the probablity that the qubit will decay to its ground
254
326
state. The probability of the qubit remaining in the same state is
255
327
therefore `1 - probability`.)#" )
328
+ .def (py::init<std::vector<double >>())
256
329
.def (py::init<double >(), py::arg (" probability" ),
257
330
" Initialize the `AmplitudeDampingChannel` with the provided "
258
- " `probability`." );
331
+ " `probability`." )
332
+ .def_readonly_static (
333
+ " num_parameters" , &litude_damping_channel::num_parameters,
334
+ " The number of parameters this channel requires at construction." );
259
335
260
336
py::class_<bit_flip_channel, kraus_channel>(
261
337
mod, " BitFlipChannel" ,
@@ -272,8 +348,12 @@ void bindNoiseChannels(py::module &mod) {
272
348
273
349
The probability of the qubit remaining in the same state is therefore `1 -
274
350
probability`.)#" )
351
+ .def (py::init<std::vector<double >>())
275
352
.def (py::init<double >(), py::arg (" probability" ),
276
- " Initialize the `BitFlipChannel` with the provided `probability`." );
353
+ " Initialize the `BitFlipChannel` with the provided `probability`." )
354
+ .def_readonly_static (
355
+ " num_parameters" , &bit_flip_channel::num_parameters,
356
+ " The number of parameters this channel requires at construction." );
277
357
278
358
py::class_<phase_flip_channel, kraus_channel>(
279
359
mod, " PhaseFlipChannel" ,
@@ -289,9 +369,92 @@ void bindNoiseChannels(py::module &mod) {
289
369
290
370
The probability of the qubit phase remaining untouched is therefore
291
371
`1 - probability`.)#" )
292
- .def (
293
- py::init<double >(), py::arg (" probability" ),
294
- " Initialize the `PhaseFlipChannel` with the provided `probability`." );
372
+ .def (py::init<std::vector<double >>())
373
+ .def (py::init<double >(), py::arg (" probability" ),
374
+ " Initialize the `PhaseFlipChannel` with the provided `probability`." )
375
+ .def_readonly_static (
376
+ " num_parameters" , &phase_flip_channel::num_parameters,
377
+ " The number of parameters this channel requires at construction." );
378
+
379
+ py::class_<phase_damping, kraus_channel>(
380
+ mod, " PhaseDamping" ,
381
+ R"#( A Kraus channel that models the single-qubit phase damping error. This
382
+ is similar to AmplitudeDamping, but for phase.)#" )
383
+ .def (py::init<std::vector<double >>())
384
+ .def (py::init<double >())
385
+ .def_readonly_static (
386
+ " num_parameters" , &phase_damping::num_parameters,
387
+ " The number of parameters this channel requires at construction." );
388
+
389
+ py::class_<z_error, kraus_channel>(
390
+ mod, " ZError" ,
391
+ R"#( A Pauli error that applies the Z operator when an error
392
+ occurs. It is the same as PhaseFlipChannel.)#" )
393
+ .def (py::init<std::vector<double >>())
394
+ .def (py::init<double >())
395
+ .def_readonly_static (
396
+ " num_parameters" , &z_error::num_parameters,
397
+ " The number of parameters this channel requires at construction." );
398
+
399
+ py::class_<x_error, kraus_channel>(
400
+ mod, " XError" ,
401
+ R"#( A Pauli error that applies the X operator when an error
402
+ occurs. It is the same as BitFlipChannel.)#" )
403
+ .def (py::init<std::vector<double >>())
404
+ .def (py::init<double >())
405
+ .def_readonly_static (
406
+ " num_parameters" , &x_error::num_parameters,
407
+ " The number of parameters this channel requires at construction." );
408
+
409
+ py::class_<y_error, kraus_channel>(
410
+ mod, " YError" ,
411
+ R"#( A Pauli error that applies the Y operator when an error
412
+ occurs.)#" )
413
+ .def (py::init<std::vector<double >>())
414
+ .def (py::init<double >())
415
+ .def_readonly_static (
416
+ " num_parameters" , &y_error::num_parameters,
417
+ " The number of parameters this channel requires at construction." );
418
+
419
+ py::class_<pauli1, kraus_channel>(
420
+ mod, " Pauli1" ,
421
+ R"#( A single-qubit Pauli error that applies either an X error, Y error,
422
+ or Z error. The probability of each X, Y, or Z error is supplied as a
423
+ parameter.)#" )
424
+ .def (py::init<std::vector<double >>())
425
+ .def_readonly_static (
426
+ " num_parameters" , &pauli1::num_parameters,
427
+ " The number of parameters this channel requires at construction." );
428
+
429
+ py::class_<pauli2, kraus_channel>(
430
+ mod, " Pauli2" ,
431
+ R"#( A 2-qubit Pauli error that applies one of the following errors, with
432
+ the probabilities specified as a vector. Possible errors: IX, IY, IZ, XI, XX,
433
+ XY, XZ, YI, YX, YY, YZ, ZI, ZX, ZY, and ZZ.)#" )
434
+ .def (py::init<std::vector<double >>())
435
+ .def_readonly_static (
436
+ " num_parameters" , &pauli2::num_parameters,
437
+ " The number of parameters this channel requires at construction." );
438
+
439
+ py::class_<depolarization1, kraus_channel>(
440
+ mod, " Depolarization1" ,
441
+ R"#( The same as DepolarizationChannel (single qubit depolarization))#" )
442
+ .def (py::init<std::vector<double >>())
443
+ .def (py::init<double >())
444
+ .def_readonly_static (
445
+ " num_parameters" , &depolarization1::num_parameters,
446
+ " The number of parameters this channel requires at construction." );
447
+
448
+ py::class_<depolarization2, kraus_channel>(
449
+ mod, " Depolarization2" ,
450
+ R"#( A 2-qubit depolarization error that applies one of the following
451
+ errors. Possible errors: IX, IY, IZ, XI, XX, XY, XZ, YI, YX, YY, YZ, ZI, ZX,
452
+ ZY, and ZZ.)#" )
453
+ .def (py::init<std::vector<double >>())
454
+ .def (py::init<double >())
455
+ .def_readonly_static (
456
+ " num_parameters" , &depolarization2::num_parameters,
457
+ " The number of parameters this channel requires at construction." );
295
458
}
296
459
297
460
void bindNoise (py::module &mod) {
0 commit comments