common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Overview
Contact
Event
Project
Research

Terms of service (Web service)

Terms of service (Quantum and ML Cloud service)

Privacy policy


Sign in
Sign up
common.title

blueqat built-in macros (draw and multi-controlled gate)

gyu-don

2021/09/16 09:09

1

Built-in macros in blueqat 0.4.7 (or later)

We released blueqat ver. 0.4.7 and implemented Gray-code based multi-controlled gates.

# Update to latest version of blueqat
!pip install -U blueqat
Requirement already satisfied: blueqat in /opt/conda/lib/python3.9/site-packages (0.4.5)
Collecting blueqat
  Downloading blueqat-0.4.7-py3-none-any.whl (66 kB)
     |████████████████████████████████| 66 kB 444 kB/s eta 0:00:011
[?25hRequirement already satisfied: scipy>=1.5 in /opt/conda/lib/python3.9/site-packages (from blueqat) (1.6.3)
Requirement already satisfied: numpy>=1.19 in /opt/conda/lib/python3.9/site-packages (from blueqat) (1.19.5)
Installing collected packages: blueqat
  Attempting uninstall: blueqat
    Found existing installation: blueqat 0.4.5
    Uninstalling blueqat-0.4.5:
      Successfully uninstalled blueqat-0.4.5
Successfully installed blueqat-0.4.7

Activate built-in macros

To activate macros, execute import blueqat.macros.

from blueqat import Circuit
import blueqat.macros

Now, built-in macros are available.

Draw the circuit

We add new macros for drawing the circuit. This feature requires qiskit.

Circuit().h[0].cx[0, 1].draw()
     ┌───┐     
q_0: ┤ H ├──■──
     └───┘┌─┴─┐
q_1: ─────┤ X ├
          └───┘
c: 2/══════════
               
# In jupyter notebook, output='mpl' generates beautiful drawing.
# You may needs to run `pip install pylatexenc` before.
Circuit().h[0].cx[0, 1].draw(output='mpl')
<Figure size 206.852x204.68 with 1 Axes>

image

Multi-controlled gate

blueqat has ccx and ccz, but doesn't have multi-controlled gate. Therefore, we implemented them as macros.

Multi-controlled X, Z

c3x, c4x, c3z, c4z are available.

Circuit.c3x(c0, c1, c2, t): 3-controlled X
Circuit.c3z(c0, c1, c2, t): 3-controlled Z
Circuit.c4x(c0, c1, c2, c3, t): 4-controlled X
Circuit.c4z(c0, c1, c2, c3, t): 4-controlled Z

for c0 in [0, 1]:
    for c1 in [0, 1]:
        for c2 in [0, 1]:
            for c3 in [0, 1]:
                c = Circuit()
                if c0:
                    c.x[0]
                if c1:
                    c.x[1]
                if c2:
                    c.x[2]
                if c3:
                    c.x[3]
                c.c4x(0, 1, 2, 3, 4)
                result = c.m[:].shots(10)
                print(f'C4x |{c0}{c1}{c2}{c3}0>')
                print(f'Expected: {c0}{c1}{c2}{c3}{c0*c1*c2*c3}, Actual:', result)
C4x |00000>
Expected: 00000, Actual: Counter({'00000': 10})
C4x |00010>
Expected: 00010, Actual: Counter({'00010': 10})
C4x |00100>
Expected: 00100, Actual: Counter({'00100': 10})
C4x |00110>
Expected: 00110, Actual: Counter({'00110': 10})
C4x |01000>
Expected: 01000, Actual: Counter({'01000': 10})
C4x |01010>
Expected: 01010, Actual: Counter({'01010': 10})
C4x |01100>
Expected: 01100, Actual: Counter({'01100': 10})
C4x |01110>
Expected: 01110, Actual: Counter({'01110': 10})
C4x |10000>
Expected: 10000, Actual: Counter({'10000': 10})
C4x |10010>
Expected: 10010, Actual: Counter({'10010': 10})
C4x |10100>
Expected: 10100, Actual: Counter({'10100': 10})
C4x |10110>
Expected: 10110, Actual: Counter({'10110': 10})
C4x |11000>
Expected: 11000, Actual: Counter({'11000': 10})
C4x |11010>
Expected: 11010, Actual: Counter({'11010': 10})
C4x |11100>
Expected: 11100, Actual: Counter({'11100': 10})
C4x |11110>
Expected: 11111, Actual: Counter({'11111': 10})

It seems OK.

We also prepared arbitrary number of control gates, mcx_gray and mcz_gray.

Circuit.mcx_gray([controls], target): Multi-controlled X
Circuit.mcz_gray([controls], target): Multi-controlled Z

c0, c1, c2 = 1, 1, 1
for c3 in [0, 1]:
    for c4 in [0, 1]:
        c = Circuit().x[0, 1, 2]
        if c3:
            c.x[3]
        if c4:
            c.x[4]
        c.mcx_gray([0, 1, 2, 3, 4], 5)
        result = c.m[:].shots(10)
        print(f'C4x |{c0}{c1}{c2}{c3}{c4}0>')
        print(f'Expected: {c0}{c1}{c2}{c3}{c4}{c0*c1*c2*c3*c4}, Actual:', result)
C4x |111000>
Expected: 111000, Actual: Counter({'111000': 10})
C4x |111010>
Expected: 111010, Actual: Counter({'111010': 10})
C4x |111100>
Expected: 111100, Actual: Counter({'111100': 10})
C4x |111110>
Expected: 111111, Actual: Counter({'111111': 10})

Please note that the number of gates is grown exponentially by the number of control qubits.

Circuit().mcx_gray([0, 1, 2], 3).draw(output='mpl')
<Figure size 1411x325.08 with 1 Axes>

image

Circuit().mcx_gray([0, 1, 2, 3], 4).draw(output='mpl')
<Figure size 1591.6x806.68 with 1 Axes>

image

Circuit().mcx_gray([0, 1, 2, 3, 4], 5).draw(output='mpl')
<Figure size 1591.6x1890.28 with 1 Axes>

image

Multi-controlled RX, RY, RZ, R

Multi-controlled rotation macros are also available.
R-gate and RZ-gate are same except global phase. However, controlled-R and controlled-RZ are different gate.

mcrx_gray(theta, [controls], target): Multi-controlled RX(theta)
mcry_gray(theta, [controls], target): Multi-controlled RY(theta)
mcrz_gray(theta, [controls], target): Multi-controlled RZ(theta)
mcr_gray(theta, [controls], target): Multi-controlled R(theta)

from math import pi

for c0 in [0, 1]:
    for c1 in [0, 1]:
        for c2 in [0, 1]:
            c = Circuit()
            if c0:
                c.x[0]
            if c1:
                c.x[1]
            if c2:
                c.x[2]
            c.mcry_gray(pi / 2, [0, 1, 2], 3)
            if c0 * c1 * c2 == 0:
                print(f"Expect: {c0}{c1}{c2}0: 100%")
            else:
                print(f"Expect: {c0}{c1}{c2}0: 50%, {c0}{c1}{c2}1: 50%")
            print("Actual:", c.m[3].shots(100))
Expect: 0000: 100%
Actual: Counter({'0000': 100})
Expect: 0010: 100%
Actual: Counter({'0000': 100})
Expect: 0100: 100%
Actual: Counter({'0000': 100})
Expect: 0110: 100%
Actual: Counter({'0000': 100})
Expect: 1000: 100%
Actual: Counter({'0000': 100})
Expect: 1010: 100%
Actual: Counter({'0000': 100})
Expect: 1100: 100%
Actual: Counter({'0000': 100})
Expect: 1110: 50%, 1111: 50%
Actual: Counter({'0001': 58, '0000': 42})

Multi-controlled U

U-gate can represent arbitrary 2x2 unitary gate with 4 parameters theta, phi, lambda and gamma.
We implemented mcu_gray macro.

mcu_gray(theta, phi, lam, gamma, [controls], target): Multi-controlled U

from blueqat.circuit_funcs import circuit_to_unitary
c = Circuit().mcu_gray(pi / 2, pi / 4, pi / 8, pi / 16, [0, 1, 2], 3)
mcu = circuit_to_unitary(c)
c.draw(output='mpl')
<Figure size 1591.6x686.28 with 1 Axes>

image

import numpy as np
u = circuit_to_unitary(Circuit().u(pi / 2, pi / 4, pi / 8, pi / 16,)[0])
expected = np.eye(16, dtype=complex)
expected[7, 7] = u[0, 0]
expected[15, 7] = u[1, 0]
expected[7, 15] = u[0, 1]
expected[15, 15] = u[1, 1]

np.allclose(mcu, expected)
True

© 2025, blueqat Inc. All rights reserved