• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Qiskit / qiskit / 13651945507

04 Mar 2025 10:46AM UTC coverage: 88.163% (+1.1%) from 87.064%
13651945507

Pull #13793

github

web-flow
Merge d11f3a53d into 47e8c9851
Pull Request #13793: Remove deprecated `BackendV1` elements, including base class, `providers.models` and `qobj` modules

33 of 71 new or added lines in 11 files covered. (46.48%)

29 existing lines in 11 files now uncovered.

75075 of 85155 relevant lines covered (88.16%)

331792.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

6.9
/qiskit/visualization/gate_map.py
1
# This code is part of Qiskit.
2
#
3
# (C) Copyright IBM 2017, 2024.
4
#
5
# This code is licensed under the Apache License, Version 2.0. You may
6
# obtain a copy of this license in the LICENSE.txt file in the root directory
7
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8
#
9
# Any modifications or derivative works of this code must retain this
10
# copyright notice, and modified files need to carry a notice indicating
11
# that they have been altered from the originals.
12

13
"""A module for visualizing device coupling maps"""
14

15
import math
1✔
16
from typing import List
1✔
17

18
import numpy as np
1✔
19
import rustworkx as rx
1✔
20
from rustworkx.visualization import graphviz_draw
1✔
21

22
from qiskit.exceptions import QiskitError
1✔
23
from qiskit.utils import optionals as _optionals
1✔
24
from qiskit.transpiler.coupling import CouplingMap
1✔
25
from .exceptions import VisualizationError
1✔
26

27

28
@_optionals.HAS_MATPLOTLIB.require_in_call
1✔
29
def plot_gate_map(
1✔
30
    backend,
31
    figsize=None,
32
    plot_directed=False,
33
    label_qubits=True,
34
    qubit_size=None,
35
    line_width=4,
36
    font_size=None,
37
    qubit_color=None,
38
    qubit_labels=None,
39
    line_color=None,
40
    font_color="white",
41
    ax=None,
42
    filename=None,
43
    qubit_coordinates=None,
44
):
45
    """Plots the gate map of a device.
46

47
    Args:
48
        backend (Backend): The backend instance that will be used to plot the device
49
            gate map.
50
        figsize (tuple): Output figure size (wxh) in inches.
51
        plot_directed (bool): Plot directed coupling map.
52
        label_qubits (bool): Label the qubits.
53
        qubit_size (float): Size of qubit marker.
54
        line_width (float): Width of lines.
55
        font_size (int): Font size of qubit labels.
56
        qubit_color (list): A list of colors for the qubits
57
        qubit_labels (list): A list of qubit labels
58
        line_color (list): A list of colors for each line from coupling_map.
59
        font_color (str): The font color for the qubit labels.
60
        ax (Axes): A Matplotlib axes instance.
61
        filename (str): file path to save image to.
62
        qubit_coordinates (Sequence): An optional sequence input (list or array being the
63
            most common) of 2d coordinates for each qubit. The length of the
64
            sequence much match the number of qubits on the backend. The sequence
65
            should be the planar coordinates in a 0-based square grid where each
66
            qubit is located.
67

68
    Returns:
69
        Figure: A Matplotlib figure instance.
70

71
    Raises:
72
        QiskitError: If you tried to pass a simulator or the backend is None,
73
            but one of num_qubits, mpl_data, or cmap is None.
74
        MissingOptionalLibraryError: If matplotlib not installed.
75

76
    Example:
77

78
        .. plot::
79
           :alt: Output from the previous code.
80
           :include-source:
81

82
           from qiskit.providers.fake_provider import GenericBackendV2
83
           from qiskit.visualization import plot_gate_map
84

85
           backend = GenericBackendV2(num_qubits=5)
86

87
           plot_gate_map(backend)
88
    """
89
    qubit_coordinates_map = {}
×
90

91
    qubit_coordinates_map[5] = [[1, 0], [0, 1], [1, 1], [1, 2], [2, 1]]
×
92

93
    qubit_coordinates_map[7] = [[0, 0], [0, 1], [0, 2], [1, 1], [2, 0], [2, 1], [2, 2]]
×
94

95
    qubit_coordinates_map[20] = [
×
96
        [0, 0],
97
        [0, 1],
98
        [0, 2],
99
        [0, 3],
100
        [0, 4],
101
        [1, 0],
102
        [1, 1],
103
        [1, 2],
104
        [1, 3],
105
        [1, 4],
106
        [2, 0],
107
        [2, 1],
108
        [2, 2],
109
        [2, 3],
110
        [2, 4],
111
        [3, 0],
112
        [3, 1],
113
        [3, 2],
114
        [3, 3],
115
        [3, 4],
116
    ]
117

118
    qubit_coordinates_map[15] = [
×
119
        [0, 0],
120
        [0, 1],
121
        [0, 2],
122
        [0, 3],
123
        [0, 4],
124
        [0, 5],
125
        [0, 6],
126
        [1, 7],
127
        [1, 6],
128
        [1, 5],
129
        [1, 4],
130
        [1, 3],
131
        [1, 2],
132
        [1, 1],
133
        [1, 0],
134
    ]
135

136
    qubit_coordinates_map[16] = [
×
137
        [1, 0],
138
        [1, 1],
139
        [2, 1],
140
        [3, 1],
141
        [1, 2],
142
        [3, 2],
143
        [0, 3],
144
        [1, 3],
145
        [3, 3],
146
        [4, 3],
147
        [1, 4],
148
        [3, 4],
149
        [1, 5],
150
        [2, 5],
151
        [3, 5],
152
        [1, 6],
153
    ]
154

155
    qubit_coordinates_map[27] = [
×
156
        [1, 0],
157
        [1, 1],
158
        [2, 1],
159
        [3, 1],
160
        [1, 2],
161
        [3, 2],
162
        [0, 3],
163
        [1, 3],
164
        [3, 3],
165
        [4, 3],
166
        [1, 4],
167
        [3, 4],
168
        [1, 5],
169
        [2, 5],
170
        [3, 5],
171
        [1, 6],
172
        [3, 6],
173
        [0, 7],
174
        [1, 7],
175
        [3, 7],
176
        [4, 7],
177
        [1, 8],
178
        [3, 8],
179
        [1, 9],
180
        [2, 9],
181
        [3, 9],
182
        [3, 10],
183
    ]
184

185
    qubit_coordinates_map[28] = [
×
186
        [0, 2],
187
        [0, 3],
188
        [0, 4],
189
        [0, 5],
190
        [0, 6],
191
        [1, 2],
192
        [1, 6],
193
        [2, 0],
194
        [2, 1],
195
        [2, 2],
196
        [2, 3],
197
        [2, 4],
198
        [2, 5],
199
        [2, 6],
200
        [2, 7],
201
        [2, 8],
202
        [3, 0],
203
        [3, 4],
204
        [3, 8],
205
        [4, 0],
206
        [4, 1],
207
        [4, 2],
208
        [4, 3],
209
        [4, 4],
210
        [4, 5],
211
        [4, 6],
212
        [4, 7],
213
        [4, 8],
214
    ]
215

216
    qubit_coordinates_map[53] = [
×
217
        [0, 2],
218
        [0, 3],
219
        [0, 4],
220
        [0, 5],
221
        [0, 6],
222
        [1, 2],
223
        [1, 6],
224
        [2, 0],
225
        [2, 1],
226
        [2, 2],
227
        [2, 3],
228
        [2, 4],
229
        [2, 5],
230
        [2, 6],
231
        [2, 7],
232
        [2, 8],
233
        [3, 0],
234
        [3, 4],
235
        [3, 8],
236
        [4, 0],
237
        [4, 1],
238
        [4, 2],
239
        [4, 3],
240
        [4, 4],
241
        [4, 5],
242
        [4, 6],
243
        [4, 7],
244
        [4, 8],
245
        [5, 2],
246
        [5, 6],
247
        [6, 0],
248
        [6, 1],
249
        [6, 2],
250
        [6, 3],
251
        [6, 4],
252
        [6, 5],
253
        [6, 6],
254
        [6, 7],
255
        [6, 8],
256
        [7, 0],
257
        [7, 4],
258
        [7, 8],
259
        [8, 0],
260
        [8, 1],
261
        [8, 2],
262
        [8, 3],
263
        [8, 4],
264
        [8, 5],
265
        [8, 6],
266
        [8, 7],
267
        [8, 8],
268
        [9, 2],
269
        [9, 6],
270
    ]
271

272
    qubit_coordinates_map[65] = [
×
273
        [0, 0],
274
        [0, 1],
275
        [0, 2],
276
        [0, 3],
277
        [0, 4],
278
        [0, 5],
279
        [0, 6],
280
        [0, 7],
281
        [0, 8],
282
        [0, 9],
283
        [1, 0],
284
        [1, 4],
285
        [1, 8],
286
        [2, 0],
287
        [2, 1],
288
        [2, 2],
289
        [2, 3],
290
        [2, 4],
291
        [2, 5],
292
        [2, 6],
293
        [2, 7],
294
        [2, 8],
295
        [2, 9],
296
        [2, 10],
297
        [3, 2],
298
        [3, 6],
299
        [3, 10],
300
        [4, 0],
301
        [4, 1],
302
        [4, 2],
303
        [4, 3],
304
        [4, 4],
305
        [4, 5],
306
        [4, 6],
307
        [4, 7],
308
        [4, 8],
309
        [4, 9],
310
        [4, 10],
311
        [5, 0],
312
        [5, 4],
313
        [5, 8],
314
        [6, 0],
315
        [6, 1],
316
        [6, 2],
317
        [6, 3],
318
        [6, 4],
319
        [6, 5],
320
        [6, 6],
321
        [6, 7],
322
        [6, 8],
323
        [6, 9],
324
        [6, 10],
325
        [7, 2],
326
        [7, 6],
327
        [7, 10],
328
        [8, 1],
329
        [8, 2],
330
        [8, 3],
331
        [8, 4],
332
        [8, 5],
333
        [8, 6],
334
        [8, 7],
335
        [8, 8],
336
        [8, 9],
337
        [8, 10],
338
    ]
339

340
    qubit_coordinates_map[127] = [
×
341
        [0, 0],
342
        [0, 1],
343
        [0, 2],
344
        [0, 3],
345
        [0, 4],
346
        [0, 5],
347
        [0, 6],
348
        [0, 7],
349
        [0, 8],
350
        [0, 9],
351
        [0, 10],
352
        [0, 11],
353
        [0, 12],
354
        [0, 13],
355
        [1, 0],
356
        [1, 4],
357
        [1, 8],
358
        [1, 12],
359
        [2, 0],
360
        [2, 1],
361
        [2, 2],
362
        [2, 3],
363
        [2, 4],
364
        [2, 5],
365
        [2, 6],
366
        [2, 7],
367
        [2, 8],
368
        [2, 9],
369
        [2, 10],
370
        [2, 11],
371
        [2, 12],
372
        [2, 13],
373
        [2, 14],
374
        [3, 2],
375
        [3, 6],
376
        [3, 10],
377
        [3, 14],
378
        [4, 0],
379
        [4, 1],
380
        [4, 2],
381
        [4, 3],
382
        [4, 4],
383
        [4, 5],
384
        [4, 6],
385
        [4, 7],
386
        [4, 8],
387
        [4, 9],
388
        [4, 10],
389
        [4, 11],
390
        [4, 12],
391
        [4, 13],
392
        [4, 14],
393
        [5, 0],
394
        [5, 4],
395
        [5, 8],
396
        [5, 12],
397
        [6, 0],
398
        [6, 1],
399
        [6, 2],
400
        [6, 3],
401
        [6, 4],
402
        [6, 5],
403
        [6, 6],
404
        [6, 7],
405
        [6, 8],
406
        [6, 9],
407
        [6, 10],
408
        [6, 11],
409
        [6, 12],
410
        [6, 13],
411
        [6, 14],
412
        [7, 2],
413
        [7, 6],
414
        [7, 10],
415
        [7, 14],
416
        [8, 0],
417
        [8, 1],
418
        [8, 2],
419
        [8, 3],
420
        [8, 4],
421
        [8, 5],
422
        [8, 6],
423
        [8, 7],
424
        [8, 8],
425
        [8, 9],
426
        [8, 10],
427
        [8, 11],
428
        [8, 12],
429
        [8, 13],
430
        [8, 14],
431
        [9, 0],
432
        [9, 4],
433
        [9, 8],
434
        [9, 12],
435
        [10, 0],
436
        [10, 1],
437
        [10, 2],
438
        [10, 3],
439
        [10, 4],
440
        [10, 5],
441
        [10, 6],
442
        [10, 7],
443
        [10, 8],
444
        [10, 9],
445
        [10, 10],
446
        [10, 11],
447
        [10, 12],
448
        [10, 13],
449
        [10, 14],
450
        [11, 2],
451
        [11, 6],
452
        [11, 10],
453
        [11, 14],
454
        [12, 1],
455
        [12, 2],
456
        [12, 3],
457
        [12, 4],
458
        [12, 5],
459
        [12, 6],
460
        [12, 7],
461
        [12, 8],
462
        [12, 9],
463
        [12, 10],
464
        [12, 11],
465
        [12, 12],
466
        [12, 13],
467
        [12, 14],
468
    ]
469

470
    qubit_coordinates_map[433] = [
×
471
        [0, 0],
472
        [0, 1],
473
        [0, 2],
474
        [0, 3],
475
        [0, 4],
476
        [0, 5],
477
        [0, 6],
478
        [0, 7],
479
        [0, 8],
480
        [0, 9],
481
        [0, 10],
482
        [0, 11],
483
        [0, 12],
484
        [0, 13],
485
        [0, 14],
486
        [0, 15],
487
        [0, 16],
488
        [0, 17],
489
        [0, 18],
490
        [0, 19],
491
        [0, 20],
492
        [0, 21],
493
        [0, 22],
494
        [0, 23],
495
        [0, 24],
496
        [0, 25],
497
        [1, 0],
498
        [1, 4],
499
        [1, 8],
500
        [1, 12],
501
        [1, 16],
502
        [1, 20],
503
        [1, 24],
504
        [2, 0],
505
        [2, 1],
506
        [2, 2],
507
        [2, 3],
508
        [2, 4],
509
        [2, 5],
510
        [2, 6],
511
        [2, 7],
512
        [2, 8],
513
        [2, 9],
514
        [2, 10],
515
        [2, 11],
516
        [2, 12],
517
        [2, 13],
518
        [2, 14],
519
        [2, 15],
520
        [2, 16],
521
        [2, 17],
522
        [2, 18],
523
        [2, 19],
524
        [2, 20],
525
        [2, 21],
526
        [2, 22],
527
        [2, 23],
528
        [2, 24],
529
        [2, 25],
530
        [2, 26],
531
        [3, 2],
532
        [3, 6],
533
        [3, 10],
534
        [3, 14],
535
        [3, 18],
536
        [3, 22],
537
        [3, 26],
538
        [4, 0],
539
        [4, 1],
540
        [4, 2],
541
        [4, 3],
542
        [4, 4],
543
        [4, 5],
544
        [4, 6],
545
        [4, 7],
546
        [4, 8],
547
        [4, 9],
548
        [4, 10],
549
        [4, 11],
550
        [4, 12],
551
        [4, 13],
552
        [4, 14],
553
        [4, 15],
554
        [4, 16],
555
        [4, 17],
556
        [4, 18],
557
        [4, 19],
558
        [4, 20],
559
        [4, 21],
560
        [4, 22],
561
        [4, 23],
562
        [4, 24],
563
        [4, 25],
564
        [4, 26],
565
        [5, 0],
566
        [5, 4],
567
        [5, 8],
568
        [5, 12],
569
        [5, 16],
570
        [5, 20],
571
        [5, 24],
572
        [6, 0],
573
        [6, 1],
574
        [6, 2],
575
        [6, 3],
576
        [6, 4],
577
        [6, 5],
578
        [6, 6],
579
        [6, 7],
580
        [6, 8],
581
        [6, 9],
582
        [6, 10],
583
        [6, 11],
584
        [6, 12],
585
        [6, 13],
586
        [6, 14],
587
        [6, 15],
588
        [6, 16],
589
        [6, 17],
590
        [6, 18],
591
        [6, 19],
592
        [6, 20],
593
        [6, 21],
594
        [6, 22],
595
        [6, 23],
596
        [6, 24],
597
        [6, 25],
598
        [6, 26],
599
        [7, 2],
600
        [7, 6],
601
        [7, 10],
602
        [7, 14],
603
        [7, 18],
604
        [7, 22],
605
        [7, 26],
606
        [8, 0],
607
        [8, 1],
608
        [8, 2],
609
        [8, 3],
610
        [8, 4],
611
        [8, 5],
612
        [8, 6],
613
        [8, 7],
614
        [8, 8],
615
        [8, 9],
616
        [8, 10],
617
        [8, 11],
618
        [8, 12],
619
        [8, 13],
620
        [8, 14],
621
        [8, 15],
622
        [8, 16],
623
        [8, 17],
624
        [8, 18],
625
        [8, 19],
626
        [8, 20],
627
        [8, 21],
628
        [8, 22],
629
        [8, 23],
630
        [8, 24],
631
        [8, 25],
632
        [8, 26],
633
        [9, 0],
634
        [9, 4],
635
        [9, 8],
636
        [9, 12],
637
        [9, 16],
638
        [9, 20],
639
        [9, 24],
640
        [10, 0],
641
        [10, 1],
642
        [10, 2],
643
        [10, 3],
644
        [10, 4],
645
        [10, 5],
646
        [10, 6],
647
        [10, 7],
648
        [10, 8],
649
        [10, 9],
650
        [10, 10],
651
        [10, 11],
652
        [10, 12],
653
        [10, 13],
654
        [10, 14],
655
        [10, 15],
656
        [10, 16],
657
        [10, 17],
658
        [10, 18],
659
        [10, 19],
660
        [10, 20],
661
        [10, 21],
662
        [10, 22],
663
        [10, 23],
664
        [10, 24],
665
        [10, 25],
666
        [10, 26],
667
        [11, 2],
668
        [11, 6],
669
        [11, 10],
670
        [11, 14],
671
        [11, 18],
672
        [11, 22],
673
        [11, 26],
674
        [12, 0],
675
        [12, 1],
676
        [12, 2],
677
        [12, 3],
678
        [12, 4],
679
        [12, 5],
680
        [12, 6],
681
        [12, 7],
682
        [12, 8],
683
        [12, 9],
684
        [12, 10],
685
        [12, 11],
686
        [12, 12],
687
        [12, 13],
688
        [12, 14],
689
        [12, 15],
690
        [12, 16],
691
        [12, 17],
692
        [12, 18],
693
        [12, 19],
694
        [12, 20],
695
        [12, 21],
696
        [12, 22],
697
        [12, 23],
698
        [12, 24],
699
        [12, 25],
700
        [12, 26],
701
        [13, 0],
702
        [13, 4],
703
        [13, 8],
704
        [13, 12],
705
        [13, 16],
706
        [13, 20],
707
        [13, 24],
708
        [14, 0],
709
        [14, 1],
710
        [14, 2],
711
        [14, 3],
712
        [14, 4],
713
        [14, 5],
714
        [14, 6],
715
        [14, 7],
716
        [14, 8],
717
        [14, 9],
718
        [14, 10],
719
        [14, 11],
720
        [14, 12],
721
        [14, 13],
722
        [14, 14],
723
        [14, 15],
724
        [14, 16],
725
        [14, 17],
726
        [14, 18],
727
        [14, 19],
728
        [14, 20],
729
        [14, 21],
730
        [14, 22],
731
        [14, 23],
732
        [14, 24],
733
        [14, 25],
734
        [14, 26],
735
        [15, 2],
736
        [15, 6],
737
        [15, 10],
738
        [15, 14],
739
        [15, 18],
740
        [15, 22],
741
        [15, 26],
742
        [16, 0],
743
        [16, 1],
744
        [16, 2],
745
        [16, 3],
746
        [16, 4],
747
        [16, 5],
748
        [16, 6],
749
        [16, 7],
750
        [16, 8],
751
        [16, 9],
752
        [16, 10],
753
        [16, 11],
754
        [16, 12],
755
        [16, 13],
756
        [16, 14],
757
        [16, 15],
758
        [16, 16],
759
        [16, 17],
760
        [16, 18],
761
        [16, 19],
762
        [16, 20],
763
        [16, 21],
764
        [16, 22],
765
        [16, 23],
766
        [16, 24],
767
        [16, 25],
768
        [16, 26],
769
        [17, 0],
770
        [17, 4],
771
        [17, 8],
772
        [17, 12],
773
        [17, 16],
774
        [17, 20],
775
        [17, 24],
776
        [18, 0],
777
        [18, 1],
778
        [18, 2],
779
        [18, 3],
780
        [18, 4],
781
        [18, 5],
782
        [18, 6],
783
        [18, 7],
784
        [18, 8],
785
        [18, 9],
786
        [18, 10],
787
        [18, 11],
788
        [18, 12],
789
        [18, 13],
790
        [18, 14],
791
        [18, 15],
792
        [18, 16],
793
        [18, 17],
794
        [18, 18],
795
        [18, 19],
796
        [18, 20],
797
        [18, 21],
798
        [18, 22],
799
        [18, 23],
800
        [18, 24],
801
        [18, 25],
802
        [18, 26],
803
        [19, 2],
804
        [19, 6],
805
        [19, 10],
806
        [19, 14],
807
        [19, 18],
808
        [19, 22],
809
        [19, 26],
810
        [20, 0],
811
        [20, 1],
812
        [20, 2],
813
        [20, 3],
814
        [20, 4],
815
        [20, 5],
816
        [20, 6],
817
        [20, 7],
818
        [20, 8],
819
        [20, 9],
820
        [20, 10],
821
        [20, 11],
822
        [20, 12],
823
        [20, 13],
824
        [20, 14],
825
        [20, 15],
826
        [20, 16],
827
        [20, 17],
828
        [20, 18],
829
        [20, 19],
830
        [20, 20],
831
        [20, 21],
832
        [20, 22],
833
        [20, 23],
834
        [20, 24],
835
        [20, 25],
836
        [20, 26],
837
        [21, 0],
838
        [21, 4],
839
        [21, 8],
840
        [21, 12],
841
        [21, 16],
842
        [21, 20],
843
        [21, 24],
844
        [22, 0],
845
        [22, 1],
846
        [22, 2],
847
        [22, 3],
848
        [22, 4],
849
        [22, 5],
850
        [22, 6],
851
        [22, 7],
852
        [22, 8],
853
        [22, 9],
854
        [22, 10],
855
        [22, 11],
856
        [22, 12],
857
        [22, 13],
858
        [22, 14],
859
        [22, 15],
860
        [22, 16],
861
        [22, 17],
862
        [22, 18],
863
        [22, 19],
864
        [22, 20],
865
        [22, 21],
866
        [22, 22],
867
        [22, 23],
868
        [22, 24],
869
        [22, 25],
870
        [22, 26],
871
        [23, 2],
872
        [23, 6],
873
        [23, 10],
874
        [23, 14],
875
        [23, 18],
876
        [23, 22],
877
        [23, 26],
878
        [24, 1],
879
        [24, 2],
880
        [24, 3],
881
        [24, 4],
882
        [24, 5],
883
        [24, 6],
884
        [24, 7],
885
        [24, 8],
886
        [24, 9],
887
        [24, 10],
888
        [24, 11],
889
        [24, 12],
890
        [24, 13],
891
        [24, 14],
892
        [24, 15],
893
        [24, 16],
894
        [24, 17],
895
        [24, 18],
896
        [24, 19],
897
        [24, 20],
898
        [24, 21],
899
        [24, 22],
900
        [24, 23],
901
        [24, 24],
902
        [24, 25],
903
        [24, 26],
904
    ]
905

NEW
906
    num_qubits = backend.num_qubits
×
NEW
907
    coupling_map = backend.coupling_map
×
NEW
908
    name = backend.name
×
909
    if qubit_coordinates is None and ("ibm" in name or "fake" in name):
×
910
        qubit_coordinates = qubit_coordinates_map.get(num_qubits, None)
×
911

912
    if qubit_coordinates:
×
913
        if len(qubit_coordinates) != num_qubits:
×
914
            raise QiskitError(
×
915
                f"The number of specified qubit coordinates {len(qubit_coordinates)} "
916
                f"does not match the device number of qubits: {num_qubits}"
917
            )
918
    return plot_coupling_map(
×
919
        num_qubits,
920
        qubit_coordinates,
921
        coupling_map.get_edges(),
922
        figsize,
923
        plot_directed,
924
        label_qubits,
925
        qubit_size,
926
        line_width,
927
        font_size,
928
        qubit_color,
929
        qubit_labels,
930
        line_color,
931
        font_color,
932
        ax,
933
        filename,
934
        planar=rx.is_planar(coupling_map.graph.to_undirected(multigraph=False)),
935
    )
936

937

938
@_optionals.HAS_MATPLOTLIB.require_in_call
1✔
939
@_optionals.HAS_GRAPHVIZ.require_in_call
1✔
940
def plot_coupling_map(
1✔
941
    num_qubits: int,
942
    qubit_coordinates: List[List[int]],
943
    coupling_map: List[List[int]],
944
    figsize=None,
945
    plot_directed=False,
946
    label_qubits=True,
947
    qubit_size=None,
948
    line_width=4,
949
    font_size=None,
950
    qubit_color=None,
951
    qubit_labels=None,
952
    line_color=None,
953
    font_color="white",
954
    ax=None,
955
    filename=None,
956
    *,
957
    planar=True,
958
):
959
    """Plots an arbitrary coupling map of qubits (embedded in a plane).
960

961
    Args:
962
        num_qubits (int): The number of qubits defined and plotted.
963
        qubit_coordinates (List[List[int]]): A list of two-element lists, with entries of each nested
964
            list being the planar coordinates in a 0-based square grid where each qubit is located.
965
        coupling_map (List[List[int]]): A list of two-element lists, with entries of each nested
966
            list being the qubit numbers of the bonds to be plotted.
967
        figsize (tuple): Output figure size (wxh) in inches.
968
        plot_directed (bool): Plot directed coupling map.
969
        label_qubits (bool): Label the qubits.
970
        qubit_size (float): Size of qubit marker.
971
        line_width (float): Width of lines.
972
        font_size (int): Font size of qubit labels.
973
        qubit_color (list): A list of colors for the qubits
974
        qubit_labels (list): A list of qubit labels
975
        line_color (list): A list of colors for each line from coupling_map.
976
        font_color (str): The font color for the qubit labels.
977
        ax (Axes): A Matplotlib axes instance.
978
        filename (str): file path to save image to.
979
        planar (bool): If the coupling map is planar or not. Default: ``True`` (i.e. it is planar)
980

981
    Returns:
982
        Figure: A Matplotlib figure instance.
983

984
    Raises:
985
        MissingOptionalLibraryError: If matplotlib or graphviz is not installed.
986
        QiskitError: If the length of qubit labels does not match the number of qubits.
987

988
    Example:
989

990
        .. plot::
991
           :alt: Output from the previous code.
992
           :include-source:
993

994
            from qiskit.visualization import plot_coupling_map
995

996
            num_qubits = 8
997
            qubit_coordinates = [[0, 1], [1, 1], [1, 0], [1, 2], [2, 0], [2, 2], [2, 1], [3, 1]]
998
            coupling_map = [[0, 1], [1, 2], [2, 3], [3, 5], [4, 5], [5, 6], [2, 4], [6, 7]]
999
            plot_coupling_map(num_qubits, qubit_coordinates, coupling_map)
1000
    """
1001
    import matplotlib.pyplot as plt
×
1002
    from .utils import matplotlib_close_if_inline
×
1003

1004
    input_axes = False
×
1005
    if ax:
×
1006
        input_axes = True
×
1007

1008
    if qubit_size is None:
×
1009
        qubit_size = 30
×
1010

1011
    if qubit_labels is None:
×
1012
        qubit_labels = list(range(num_qubits))
×
1013
    else:
1014
        if len(qubit_labels) != num_qubits:
×
1015
            raise QiskitError("Length of qubit labels does not equal number of qubits.")
×
1016

1017
    if not label_qubits:
×
1018
        qubit_labels = [""] * num_qubits
×
1019

1020
    # set coloring
1021
    if qubit_color is None:
×
1022
        qubit_color = ["#648fff"] * num_qubits
×
1023
    if line_color is None:
×
1024
        line_color = ["#648fff"] * len(coupling_map)
×
1025

1026
    if num_qubits == 1:
×
1027
        graph = rx.PyDiGraph()
×
1028
        graph.add_node(0)
×
1029
    else:
1030
        graph = CouplingMap(coupling_map).graph
×
1031

1032
    if not plot_directed:
×
1033
        line_color_map = dict(zip(graph.edge_list(), line_color))
×
1034
        graph = graph.to_undirected(multigraph=False)
×
1035
        line_color = [line_color_map[edge] for edge in graph.edge_list()]
×
1036

1037
    for node in graph.node_indices():
×
1038
        graph[node] = node
×
1039

1040
    for edge_index in graph.edge_indices():
×
1041
        graph.update_edge_by_index(edge_index, edge_index)
×
1042

1043
    # pixel-to-inch conversion
1044
    px = 1.15 / plt.rcParams["figure.dpi"]
×
1045

1046
    if qubit_coordinates:
×
1047
        qubit_coordinates = [coordinates[::-1] for coordinates in qubit_coordinates]
×
1048

1049
    if font_size is None:
×
1050
        max_characters = max(1, max(len(str(x)) for x in qubit_labels))
×
1051
        if max_characters == 1:
×
1052
            font_size = 20
×
1053
        elif max_characters == 2:
×
1054
            font_size = 14
×
1055
        elif max_characters == 3:
×
1056
            font_size = 12
×
1057
        else:
1058
            font_size = 1
×
1059

1060
    def color_node(node):
×
1061
        if qubit_coordinates:
×
1062
            out_dict = {
×
1063
                "label": str(qubit_labels[node]),
1064
                "color": f'"{qubit_color[node]}"',
1065
                "fillcolor": f'"{qubit_color[node]}"',
1066
                "pos": f'"{qubit_coordinates[node][0]},{qubit_coordinates[node][1]}"',
1067
                "pin": "True",
1068
            }
1069
        else:
1070
            out_dict = {
×
1071
                "label": str(qubit_labels[node]),
1072
                "color": f'"{qubit_color[node]}"',
1073
                "fillcolor": f'"{qubit_color[node]}"',
1074
            }
1075
        out_dict["style"] = "filled"
×
1076
        out_dict["shape"] = "circle"
×
1077
        out_dict["fontcolor"] = f'"{font_color}"'
×
1078
        out_dict["fontsize"] = f'"{str(font_size)}!"'
×
1079
        out_dict["height"] = str(qubit_size * px)
×
1080
        out_dict["fixedsize"] = "True"
×
1081
        out_dict["fontname"] = '"DejaVu Sans"'
×
1082
        return out_dict
×
1083

1084
    def color_edge(edge):
×
1085
        out_dict = {
×
1086
            "color": f'"{line_color[edge]}"',
1087
            "fillcolor": f'"{line_color[edge]}"',
1088
            "penwidth": str(line_width),
1089
        }
1090
        return out_dict
×
1091

1092
    graph_attributes = None
×
1093
    if not qubit_coordinates:
×
1094
        if planar:
×
1095
            graph_attributes = {
×
1096
                "overlap_scaling": "-7",
1097
                "overlap": "prism",
1098
                "model": "subset",
1099
            }
1100
        else:
1101
            graph_attributes = {
×
1102
                "overlap": "true",
1103
            }
1104
    plot = graphviz_draw(
×
1105
        graph,
1106
        method="neato",
1107
        graph_attr=graph_attributes,
1108
        node_attr_fn=color_node,
1109
        edge_attr_fn=color_edge,
1110
        filename=filename,
1111
    )
1112

1113
    if filename:
×
1114
        return None
×
1115

1116
    if not input_axes:
×
1117
        if figsize is None:
×
1118
            width, height = plot.size
×
1119
            figsize = (width * px, height * px)
×
1120
        fig, ax = plt.subplots(figsize=figsize)
×
1121
    ax.axis("off")
×
1122
    ax.imshow(plot)
×
1123

1124
    if not input_axes:
×
1125
        matplotlib_close_if_inline(fig)
×
1126
        return fig
×
1127

1128

1129
def plot_circuit_layout(circuit, backend, view="virtual", qubit_coordinates=None):
1✔
1130
    """Plot the layout of a circuit transpiled for a given
1131
    target backend.
1132

1133
    Args:
1134
        circuit (QuantumCircuit): Input quantum circuit.
1135
        backend (Backend): Target backend.
1136
        view (str): How to label qubits in the layout. Options:
1137

1138
          - ``"virtual"``: Label each qubit with the index of the virtual qubit that
1139
            mapped to it.
1140
          - ``"physical"``: Label each qubit with the index of the physical qubit that it
1141
            corresponds to on the device.
1142

1143
        qubit_coordinates (Sequence): An optional sequence input (list or array being the
1144
            most common) of 2d coordinates for each qubit. The length of the
1145
            sequence must match the number of qubits on the backend. The sequence
1146
            should be the planar coordinates in a 0-based square grid where each
1147
            qubit is located.
1148

1149
    Returns:
1150
        Figure: A matplotlib figure showing layout.
1151

1152
    Raises:
1153
        QiskitError: Invalid view type given.
1154
        VisualizationError: Circuit has no layout attribute.
1155

1156
    Example:
1157
        .. plot::
1158
           :alt: Output from the previous code.
1159
           :include-source:
1160

1161
            from qiskit import QuantumCircuit, transpile
1162
            from qiskit.providers.fake_provider import GenericBackendV2
1163
            from qiskit.visualization import plot_circuit_layout
1164

1165
            ghz = QuantumCircuit(3, 3)
1166
            ghz.h(0)
1167
            for idx in range(1,3):
1168
                ghz.cx(0,idx)
1169
            ghz.measure(range(3), range(3))
1170

1171
            backend = GenericBackendV2(num_qubits=5)
1172
            new_circ_lv3 = transpile(ghz, backend=backend, optimization_level=3)
1173
            plot_circuit_layout(new_circ_lv3, backend)
1174
    """
1175
    if circuit._layout is None:
×
1176
        raise QiskitError("Circuit has no layout. Perhaps it has not been transpiled.")
×
1177

NEW
1178
    num_qubits = backend.num_qubits
×
NEW
1179
    cmap = backend.coupling_map
×
NEW
1180
    cmap_len = cmap.graph.num_edges()
×
1181

1182
    qubits = []
×
1183
    qubit_labels = [""] * num_qubits
×
1184

1185
    bit_locations = {
×
1186
        bit: {"register": register, "index": index}
1187
        for register in circuit._layout.initial_layout.get_registers()
1188
        for index, bit in enumerate(register)
1189
    }
1190
    for index, qubit in enumerate(circuit._layout.initial_layout.get_virtual_bits()):
×
1191
        if qubit not in bit_locations:
×
1192
            bit_locations[qubit] = {"register": None, "index": index}
×
1193

1194
    if view == "virtual":
×
1195
        for key, val in circuit._layout.initial_layout.get_virtual_bits().items():
×
1196
            bit_register = bit_locations[key]["register"]
×
1197
            if bit_register is None or bit_register.name != "ancilla":
×
1198
                qubits.append(val)
×
1199
                qubit_labels[val] = str(bit_locations[key]["index"])
×
1200

1201
    elif view == "physical":
×
1202
        for key, val in circuit._layout.initial_layout.get_physical_bits().items():
×
1203
            bit_register = bit_locations[val]["register"]
×
1204
            if bit_register is None or bit_register.name != "ancilla":
×
1205
                qubits.append(key)
×
1206
                qubit_labels[key] = str(key)
×
1207

1208
    else:
1209
        raise VisualizationError("Layout view must be 'virtual' or 'physical'.")
×
1210

1211
    qcolors = ["#648fff"] * num_qubits
×
1212
    for k in qubits:
×
1213
        qcolors[k] = "black"
×
1214

1215
    lcolors = ["#648fff"] * cmap_len
×
1216

1217
    for idx, edge in enumerate(cmap):
×
1218
        if edge[0] in qubits and edge[1] in qubits:
×
1219
            lcolors[idx] = "black"
×
1220

1221
    fig = plot_gate_map(
×
1222
        backend,
1223
        qubit_color=qcolors,
1224
        qubit_labels=qubit_labels,
1225
        line_color=lcolors,
1226
        qubit_coordinates=qubit_coordinates,
1227
    )
1228
    return fig
×
1229

1230

1231
@_optionals.HAS_MATPLOTLIB.require_in_call
1✔
1232
@_optionals.HAS_SEABORN.require_in_call
1✔
1233
def plot_error_map(backend, figsize=(15, 12), show_title=True, qubit_coordinates=None):
1✔
1234
    """Plots the error map of a given backend.
1235

1236
    Args:
1237
        backend (Backend): Given backend.
1238
        figsize (tuple): Figure size in inches.
1239
        show_title (bool): Show the title or not.
1240
        qubit_coordinates (Sequence): An optional sequence input (list or array being the
1241
            most common) of 2d coordinates for each qubit. The length of the
1242
            sequence much mast the number of qubits on the backend. The sequence
1243
            should be the planar coordinates in a 0-based square grid where each
1244
            qubit is located.
1245

1246
    Returns:
1247
        Figure: A matplotlib figure showing error map.
1248

1249
    Raises:
1250
        VisualizationError: The backend does not provide gate errors for the 'sx' gate.
1251
        MissingOptionalLibraryError: If matplotlib or seaborn is not installed.
1252

1253
    Example:
1254
        .. plot::
1255
           :alt: Output from the previous code.
1256
           :include-source:
1257

1258
            from qiskit.visualization import plot_error_map
1259
            from qiskit.providers.fake_provider import GenericBackendV2
1260

1261
            backend = GenericBackendV2(num_qubits=5)
1262
            plot_error_map(backend)
1263
    """
1264
    import matplotlib
×
1265
    import matplotlib.pyplot as plt
×
1266
    from matplotlib import gridspec, ticker
×
1267
    import seaborn as sns
×
1268
    from .utils import matplotlib_close_if_inline
×
1269

1270
    color_map = sns.cubehelix_palette(reverse=True, as_cmap=True)
×
1271

NEW
1272
    backend_name = backend.name
×
NEW
1273
    num_qubits = backend.num_qubits
×
NEW
1274
    cmap = backend.coupling_map
×
NEW
1275
    two_q_error_map = {}
×
NEW
1276
    single_gate_errors = [0] * num_qubits
×
NEW
1277
    read_err = [0] * num_qubits
×
NEW
1278
    cx_errors = []
×
NEW
1279
    for gate, prop_dict in backend.target.items():
×
NEW
1280
        if prop_dict is None or None in prop_dict:
×
NEW
1281
            continue
×
NEW
1282
        for qargs, inst_props in prop_dict.items():
×
NEW
1283
            if inst_props is None:
×
1284
                continue
×
NEW
1285
            if gate == "measure":
×
NEW
1286
                if inst_props.error is not None:
×
NEW
1287
                    read_err[qargs[0]] = inst_props.error
×
NEW
1288
            elif len(qargs) == 1:
×
NEW
1289
                if inst_props.error is not None:
×
NEW
1290
                    single_gate_errors[qargs[0]] = max(
×
1291
                        single_gate_errors[qargs[0]], inst_props.error
1292
                    )
NEW
1293
            elif len(qargs) == 2:
×
NEW
1294
                if inst_props.error is not None:
×
NEW
1295
                    two_q_error_map[qargs] = max(two_q_error_map.get(qargs, 0), inst_props.error)
×
NEW
1296
    if cmap:
×
NEW
1297
        directed = False
×
NEW
1298
        if num_qubits < 20:
×
NEW
1299
            for edge in cmap:
×
NEW
1300
                if not [edge[1], edge[0]] in cmap:
×
NEW
1301
                    directed = True
×
NEW
1302
                    break
×
NEW
1303
        for line in cmap.get_edges():
×
NEW
1304
            err = two_q_error_map.get(tuple(line), 0)
×
NEW
1305
            cx_errors.append(err)
×
1306

1307
    # Convert to percent
1308
    single_gate_errors = 100 * np.asarray(single_gate_errors)
×
1309
    avg_1q_err = np.mean(single_gate_errors)
×
1310

1311
    single_norm = matplotlib.colors.Normalize(
×
1312
        vmin=min(single_gate_errors), vmax=max(single_gate_errors)
1313
    )
1314
    q_colors = [matplotlib.colors.to_hex(color_map(single_norm(err))) for err in single_gate_errors]
×
1315

1316
    directed = False
×
1317
    line_colors = []
×
1318
    if cmap:
×
1319

1320
        # Convert to percent
1321
        cx_errors = 100 * np.asarray(cx_errors)
×
1322
        avg_cx_err = np.mean(cx_errors)
×
1323

1324
        cx_norm = matplotlib.colors.Normalize(vmin=min(cx_errors), vmax=max(cx_errors))
×
1325
        line_colors = [matplotlib.colors.to_hex(color_map(cx_norm(err))) for err in cx_errors]
×
1326

1327
    read_err = 100 * np.asarray(read_err)
×
1328
    avg_read_err = np.mean(read_err)
×
1329
    max_read_err = np.max(read_err)
×
1330

1331
    fig = plt.figure(figsize=figsize)
×
1332
    gridspec.GridSpec(nrows=2, ncols=3)
×
1333

1334
    grid_spec = gridspec.GridSpec(
×
1335
        12, 12, height_ratios=[1] * 11 + [0.5], width_ratios=[2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]
1336
    )
1337

1338
    left_ax = plt.subplot(grid_spec[2:10, :1])
×
1339
    main_ax = plt.subplot(grid_spec[:11, 1:11])
×
1340
    right_ax = plt.subplot(grid_spec[2:10, 11:])
×
1341
    bleft_ax = plt.subplot(grid_spec[-1, :5])
×
1342
    if cmap:
×
1343
        bright_ax = plt.subplot(grid_spec[-1, 7:])
×
1344

1345
    qubit_size = 28
×
1346
    if num_qubits <= 5:
×
1347
        qubit_size = 20
×
1348
    plot_gate_map(
×
1349
        backend,
1350
        qubit_color=q_colors,
1351
        line_color=line_colors,
1352
        qubit_size=qubit_size,
1353
        line_width=5,
1354
        plot_directed=directed,
1355
        ax=main_ax,
1356
        qubit_coordinates=qubit_coordinates,
1357
    )
1358

1359
    main_ax.axis("off")
×
1360
    main_ax.set_aspect(1)
×
1361
    if cmap:
×
1362
        single_cb = matplotlib.colorbar.ColorbarBase(
×
1363
            bleft_ax, cmap=color_map, norm=single_norm, orientation="horizontal"
1364
        )
1365
        tick_locator = ticker.MaxNLocator(nbins=5)
×
1366
        single_cb.locator = tick_locator
×
1367
        single_cb.update_ticks()
×
1368
        single_cb.update_ticks()
×
1369
        bleft_ax.set_title(f"H error rate (%) [Avg. = {round(avg_1q_err, 3)}]")
×
1370

1371
    if cmap is None:
×
1372
        bleft_ax.axis("off")
×
1373
        bleft_ax.set_title(f"H error rate (%) = {round(avg_1q_err, 3)}")
×
1374

1375
    if cmap:
×
1376
        cx_cb = matplotlib.colorbar.ColorbarBase(
×
1377
            bright_ax, cmap=color_map, norm=cx_norm, orientation="horizontal"
1378
        )
1379
        tick_locator = ticker.MaxNLocator(nbins=5)
×
1380
        cx_cb.locator = tick_locator
×
1381
        cx_cb.update_ticks()
×
1382
        bright_ax.set_title(f"CNOT error rate (%) [Avg. = {round(avg_cx_err, 3)}]")
×
1383

1384
    if num_qubits < 10:
×
1385
        num_left = num_qubits
×
1386
        num_right = 0
×
1387
    else:
1388
        num_left = math.ceil(num_qubits / 2)
×
1389
        num_right = num_qubits - num_left
×
1390

1391
    left_ax.barh(range(num_left), read_err[:num_left], align="center", color="#DDBBBA")
×
1392
    left_ax.axvline(avg_read_err, linestyle="--", color="#212121")
×
1393
    left_ax.set_yticks(range(num_left))
×
1394
    left_ax.set_xticks([0, round(avg_read_err, 2), round(max_read_err, 2)])
×
1395
    left_ax.set_yticklabels([str(kk) for kk in range(num_left)], fontsize=12)
×
1396
    left_ax.invert_yaxis()
×
1397
    left_ax.set_title("Readout Error (%)", fontsize=12)
×
1398

1399
    for spine in left_ax.spines.values():
×
1400
        spine.set_visible(False)
×
1401

1402
    if num_right:
×
1403
        right_ax.barh(
×
1404
            range(num_left, num_qubits), read_err[num_left:], align="center", color="#DDBBBA"
1405
        )
1406
        right_ax.axvline(avg_read_err, linestyle="--", color="#212121")
×
1407
        right_ax.set_yticks(range(num_left, num_qubits))
×
1408
        right_ax.set_xticks([0, round(avg_read_err, 2), round(max_read_err, 2)])
×
1409
        right_ax.set_yticklabels([str(kk) for kk in range(num_left, num_qubits)], fontsize=12)
×
1410
        right_ax.invert_yaxis()
×
1411
        right_ax.invert_xaxis()
×
1412
        right_ax.yaxis.set_label_position("right")
×
1413
        right_ax.yaxis.tick_right()
×
1414
        right_ax.set_title("Readout Error (%)", fontsize=12)
×
1415
    else:
1416
        right_ax.axis("off")
×
1417

1418
    for spine in right_ax.spines.values():
×
1419
        spine.set_visible(False)
×
1420

1421
    if show_title:
×
1422
        fig.suptitle(f"{backend_name} Error Map", fontsize=24, y=0.9)
×
1423
    matplotlib_close_if_inline(fig)
×
1424
    return fig
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc