quantumsim / qsoverlay

An overlay for the quantumsim package developed by Brian Tarasinski (https://github.com/brianzi/quantumsim)
GNU General Public License v3.0
2 stars 4 forks source link

QSoverlay generating wrong circuits, when gate time is supplied... #19

Open Astlaan opened 4 years ago

Astlaan commented 4 years ago

I created a circuit using overlay. However, qsoverlay generates wrong quantumsim code. I tried simulating both the intented circuit (written in qsoverlay) and the resulting circuit (exported by qsoverlay) and the simulation results do not match. This is supposed to be a deterministic computation, which is not the case on the quantumsim circuit generated by qsoverlay (I set noise_flag = False during the function call.)

Here's the qsoverlay circuit:

def circuit_generated(noise_flag, setup_name = 'DiCarlo_setup'):
    qubit_list = ['0', '2', '3', '5', '6']
    if setup_name == 'DiCarlo_setup':
        setup = DiCarlo_setup.quick_setup(qubit_list, noise_flag = noise_flag)
    b = Builder(setup)
    b.new_circuit(circuit_title = 'cuccaroAdder_1b_mapped')
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 10)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 10)
    b.add_gate('CZ', ['2', '5'], time = 40)
    b.add_gate('RY', ['5'], angle = np.pi/2, time = 70)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 70)
    b.add_gate('CZ', ['5', '2'], time = 100)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 130)
    b.add_gate('RY', ['0'], angle = -np.pi/2, time = 130)
    b.add_gate('CZ', ['2', '0'], time = 160)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 190)
    b.add_gate('CZ', ['2', '5'], time = 220)
    b.add_gate('RY', ['5'], angle = np.pi/2, time = 250)
    b.add_gate('CZ', ['2', '5'], time = 280)
    b.add_gate('Y', ['0'], time = 310)
    b.add_gate('RX', ['0'], angle = -np.pi/4, time = 330)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 330)
    b.add_gate('X', ['2'], time = 350)
    b.add_gate('Y', ['0'], time = 350)
    b.add_gate('CZ', ['2', '0'], time = 380)
    b.add_gate('Y', ['5'], time = 410)
    b.add_gate('RX', ['5'], angle = -np.pi/4, time = 430)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 450)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 450)
    b.add_gate('CZ', ['5', '2'], time = 480)
    b.add_gate('Y', ['2'], time = 510)
    b.add_gate('RX', ['2'], angle = np.pi/4, time = 530)
    b.add_gate('Y', ['2'], time = 550)
    b.add_gate('CZ', ['5', '2'], time = 580)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 610)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 610)
    b.add_gate('CZ', ['2', '5'], time = 640)
    b.add_gate('RY', ['5'], angle = np.pi/2, time = 670)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 670)
    b.add_gate('CZ', ['5', '2'], time = 700)
    b.add_gate('Y', ['0'], time = 730)
    b.add_gate('RX', ['0'], angle = np.pi/4, time = 750)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 770)
    b.add_gate('Y', ['0'], time = 770)
    b.add_gate('CZ', ['2', '0'], time = 800)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 830)
    b.add_gate('CZ', ['2', '5'], time = 860)
    b.add_gate('CZ', ['2', '5'], time = 900)
    b.add_gate('RY', ['5'], angle = np.pi/2, time = 930)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 930)
    b.add_gate('CZ', ['5', '2'], time = 960)
    b.add_gate('Y', ['0'], time = 990)
    b.add_gate('RX', ['0'], angle = -np.pi/4, time = 1010)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 1030)
    b.add_gate('Y', ['0'], time = 1030)
    b.add_gate('CZ', ['2', '0'], time = 1060)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 1090)
    b.add_gate('CZ', ['2', '5'], time = 1120)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 1150)
    b.add_gate('RX', ['2'], angle = -np.pi/4, time = 1170)
    b.add_gate('X', ['2'], time = 1190)
    b.add_gate('CZ', ['2', '5'], time = 1220)
    b.add_gate('RY', ['5'], angle = np.pi/2, time = 1250)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 1250)
    b.add_gate('CZ', ['5', '2'], time = 1280)
    b.add_gate('Y', ['0'], time = 1310)
    b.add_gate('RX', ['0'], angle = np.pi/4, time = 1330)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 1350)
    b.add_gate('Y', ['0'], time = 1350)
    b.add_gate('CZ', ['2', '0'], time = 1380)
    b.add_gate('RY', ['3'], angle = -np.pi/2, time = 1410)
    b.add_gate('RY', ['6'], angle = -np.pi/2, time = 1410)
    b.add_gate('CZ', ['3', '6'], time = 1440)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 1450)
    b.add_gate('CZ', ['2', '5'], time = 1480)
    b.add_gate('RY', ['3'], angle = -np.pi/2, time = 1490)
    b.add_gate('RY', ['6'], angle = np.pi/2, time = 1510)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 1510)
    b.add_gate('CZ', ['6', '3'], time = 1540)
    b.add_gate('RX', ['2'], angle = -np.pi/4, time = 1530)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 1550)
    b.add_gate('CZ', ['2', '5'], time = 1580)
    b.add_gate('RY', ['3'], angle = np.pi/2, time = 1610)
    b.add_gate('RY', ['6'], angle = -np.pi/2, time = 1610)
    b.add_gate('CZ', ['3', '6'], time = 1640)
    b.add_gate('RY', ['5'], angle = np.pi/2, time = 1650)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 1650)
    b.add_gate('CZ', ['5', '2'], time = 1680)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 1710)
    b.add_gate('RY', ['6'], angle = np.pi/2, time = 1710)
    b.add_gate('CZ', ['2', '6'], time = 1740)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 1770)
    b.add_gate('CZ', ['2', '5'], time = 1800)
    b.add_gate('Y', ['0'], time = 1830)
    b.add_gate('RX', ['0'], angle = -np.pi/4, time = 1850)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 1850)
    b.add_gate('X', ['2'], time = 1870)
    b.add_gate('Y', ['0'], time = 1870)
    b.add_gate('CZ', ['2', '0'], time = 1900)
    b.add_gate('RY', ['5'], angle = np.pi/2, time = 1930)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 1930)
    b.add_gate('CZ', ['5', '2'], time = 1960)
    b.add_gate('Y', ['2'], time = 1990)
    b.add_gate('RX', ['2'], angle = np.pi/4, time = 2010)
    b.add_gate('Y', ['2'], time = 2030)
    b.add_gate('CZ', ['5', '2'], time = 2060)
    b.add_gate('Y', ['0'], time = 2090)
    b.add_gate('RX', ['0'], angle = np.pi/4, time = 2110)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 2130)
    b.add_gate('RY', ['0'], angle = np.pi/2, time = 2130)
    b.add_gate('CZ', ['2', '0'], time = 2160)
    b.add_gate('RY', ['0'], angle = np.pi/2, time = 2190)
    b.add_gate('RY', ['2'], angle = -np.pi/2, time = 2190)
    b.add_gate('CZ', ['0', '2'], time = 2220)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 2250)
    b.add_gate('CZ', ['5', '2'], time = 2280)
    b.add_gate('RY', ['0'], angle = -np.pi/2, time = 2310)
    b.add_gate('CZ', ['2', '0'], time = 2340)
    b.add_gate('Y', ['2'], time = 2370)
    b.add_gate('RX', ['2'], angle = -np.pi/4, time = 2390)
    b.add_gate('RY', ['0'], angle = np.pi/2, time = 2410)
    b.add_gate('Y', ['2'], time = 2410)
    b.add_gate('CZ', ['0', '2'], time = 2440)
    b.add_gate('Y', ['2'], time = 2470)
    b.add_gate('RX', ['2'], angle = np.pi/4, time = 2490)
    b.add_gate('Y', ['2'], time = 2510)
    b.add_gate('CZ', ['5', '2'], time = 2540)
    b.add_gate('RY', ['0'], angle = np.pi/2, time = 2570)
    b.add_gate('RX', ['0'], angle = -np.pi/4, time = 2590)
    b.add_gate('X', ['0'], time = 2610)
    b.add_gate('CZ', ['0', '2'], time = 2640)
    b.add_gate('RY', ['2'], angle = np.pi/2, time = 2670)
    b.add_gate('RY', ['5'], angle = -np.pi/2, time = 2670)
    b.add_gate('CZ', ['2', '5'], time = 2700)
    b.add_gate('RY', ['5'], angle = np.pi/2, time = 2730)
    b.add_gate('RY', ['6'], angle = np.pi/2, time = 2730)

    b.times = {'0' : 2660, '2' : 2720, '3' : 1660, '5' : 2740, '6' : 2740}

    b.finalize()
    return b.circuit

c = circuit_generated(False)
state = SparseDM(c.get_qubit_names())
c.apply_to(state)
measurement_result = state.peak_multiple_measurements(c.get_qubit_names())
for measurement_case in measurement_result:
    print(measurement_case[1])  #This prints the measurement probability of each output string

If I run this code, I get the result below:

-1.3142147818292288e-16
0.5000000000000118
-3.8248997576827744e-16
-2.2007207689895543e-17
2.7377991625662594e-16
-7.775806874839379e-17
-3.6082248300317523e-16
2.3810921612925877e-17
3.787268627528983e-32
-1.0087110361944384e-16
7.986799417756771e-18
-4.54207160597585e-33
-6.831923780161309e-32
-1.230828848845301e-17
3.293859402450043e-17
-1.1174990543297683e-32
1.7250638167072632e-17
-4.163336342344331e-16
-8.620627214407865e-17
-8.901509477261951e-17
-5.1735311331593927e-17
-7.965570795948258e-16
0.5000000000000119
-6.54297685854598e-17
-5.5129737483937296e-33
1.8507847265717466e-17
1.6372998429493882e-17
3.6947847358860225e-32
1.1138104132564228e-32
7.842364397068003e-18
-1.0577764255283065e-16
4.106711883610084e-33

As can be seen, the probability distribution is concentrated in 2 outputs (with 50% chance each), instead of just in one output, as calculated for the equivalent cQasm circuit in Quantum Inspire.

Astlaan commented 4 years ago

This is the desired, correct circuit, that I have written in qsoverlay:

RY q[2], -1.57079633, time = 10
RY q[5], -1.57079633, time = 10
CZ q[2], q[5], time = 40
RY q[5], 1.57079633, time = 70
RY q[2], -1.57079633, time = 70
CZ q[5], q[2], time = 100
RY q[2], 1.57079633, time = 130
RY q[0], -1.57079633, time = 130
CZ q[2], q[0], time = 160
RY q[5], -1.57079633, time = 190
CZ q[2], q[5], time = 220
RY q[5], 1.57079633, time = 250
CZ q[2], q[5], time = 280
Y q[0], time = 310
RX q[0], -0.785398163, time = 330
RY q[2], 1.57079633, time = 330
X q[2], time = 350
Y q[0], time = 350
CZ q[2], q[0], time = 380
Y q[5], time = 410
RX q[5], -0.785398163, time = 430
RY q[5], -1.57079633, time = 450
RY q[2], -1.57079633, time = 450
CZ q[5], q[2], time = 480
Y q[2], time = 510
RX q[2], 0.785398163, time = 530
Y q[2], time = 550
CZ q[5], q[2], time = 580
RY q[2], 1.57079633, time = 610
RY q[5], -1.57079633, time = 610
CZ q[2], q[5], time = 640
RY q[5], 1.57079633, time = 670
RY q[2], -1.57079633, time = 670
CZ q[5], q[2], time = 700
Y q[0], time = 730
RX q[0], 0.785398163, time = 750
RY q[2], 1.57079633, time = 770
Y q[0], time = 770
CZ q[2], q[0], time = 800
RY q[5], -1.57079633, time = 830
CZ q[2], q[5], time = 860
CZ q[2], q[5], time = 900
RY q[5], 1.57079633, time = 930
RY q[2], -1.57079633, time = 930
CZ q[5], q[2], time = 960
Y q[0], time = 990
RX q[0], -0.785398163, time = 1010
RY q[2], 1.57079633, time = 1030
Y q[0], time = 1030
CZ q[2], q[0], time = 1060
RY q[5], -1.57079633, time = 1090
CZ q[2], q[5], time = 1120
RY q[2], 1.57079633, time = 1150
RX q[2], -0.785398163, time = 1170
X q[2], time = 1190
CZ q[2], q[5], time = 1220
RY q[5], 1.57079633, time = 1250
RY q[2], -1.57079633, time = 1250
CZ q[5], q[2], time = 1280
Y q[0], time = 1310
RX q[0], 0.785398163, time = 1330
RY q[2], 1.57079633, time = 1350
Y q[0], time = 1350
CZ q[2], q[0], time = 1380
RY q[3], -1.57079633, time = 1410
RY q[6], -1.57079633, time = 1410
CZ q[3], q[6], time = 1440
RY q[5], -1.57079633, time = 1450
CZ q[2], q[5], time = 1480
RY q[3], -1.57079633, time = 1490
RY q[6], 1.57079633, time = 1510
RY q[2], 1.57079633, time = 1510
CZ q[6], q[3], time = 1540
RX q[2], -0.785398163, time = 1530
RY q[2], -1.57079633, time = 1550
CZ q[2], q[5], time = 1580
RY q[3], 1.57079633, time = 1610
RY q[6], -1.57079633, time = 1610
CZ q[3], q[6], time = 1640
RY q[5], 1.57079633, time = 1650
RY q[2], -1.57079633, time = 1650
CZ q[5], q[2], time = 1680
RY q[2], 1.57079633, time = 1710
RY q[6], 1.57079633, time = 1710
CZ q[2], q[6], time = 1740
RY q[5], -1.57079633, time = 1770
CZ q[2], q[5], time = 1800
Y q[0], time = 1830
RX q[0], -0.785398163, time = 1850
RY q[2], 1.57079633, time = 1850
X q[2], time = 1870
Y q[0], time = 1870
CZ q[2], q[0], time = 1900
RY q[5], 1.57079633, time = 1930
RY q[2], -1.57079633, time = 1930
CZ q[5], q[2], time = 1960
Y q[2], time = 1990
RX q[2], 0.785398163, time = 2010
Y q[2], time = 2030
CZ q[5], q[2], time = 2060
Y q[0], time = 2090
RX q[0], 0.785398163, time = 2110
RY q[2], 1.57079633, time = 2130
RY q[0], 1.57079633, time = 2130
CZ q[2], q[0], time = 2160
RY q[0], 1.57079633, time = 2190
RY q[2], -1.57079633, time = 2190
CZ q[0], q[2], time = 2220
RY q[2], 1.57079633, time = 2250
CZ q[5], q[2], time = 2280
RY q[0], -1.57079633, time = 2310
CZ q[2], q[0], time = 2340
Y q[2], time = 2370
RX q[2], -0.785398163, time = 2390
RY q[0], 1.57079633, time = 2410
Y q[2], time = 2410
CZ q[0], q[2], time = 2440
Y q[2], time = 2470
RX q[2], 0.785398163, time = 2490
Y q[2], time = 2510
CZ q[5], q[2], time = 2540
RY q[0], 1.57079633, time = 2570
RX q[0], -0.785398163, time = 2590
X q[0], time = 2610
CZ q[0], q[2], time = 2640
RY q[2], 1.57079633, time = 2670
RY q[5], -1.57079633, time = 2670
CZ q[2], q[5], time = 2700
RY q[5], 1.57079633, time = 2730
RY q[6], 1.57079633, time = 2730

And this is the code qsoverlay outputs:

RY, q[2], -1.57079633, time: 10
RY, q[5], -1.57079633, time: 10
RY, q[0], -3.14159265, time: 10.0
RX, q[2], -3.14159265, time: 10.0
RY, q[5], -3.14159265, time: 10.0
RY, q[0], -3.14159265, time: 30.0
RY, q[2], -3.14159265, time: 30.0
CZ, q[2], q[2], time: 40
RY, q[2], -3.14159265, time: 50.0
RY, q[0], -3.14159265, time: 50.0
RY, q[5], 1.57079633, time: 70
RY, q[2], -1.57079633, time: 70
RY, q[0], -3.14159265, time: 70.0
RX, q[2], -3.14159265, time: 70.0
RY, q[0], -3.14159265, time: 90.0
RX, q[2], -3.14159265, time: 90.0
CZ, q[5], q[5], time: 100
RY, q[0], -3.14159265, time: 110.0
RY, q[2], -3.14159265, time: 110.0
RY, q[2], 1.57079633, time: 130
RY, q[0], -1.57079633, time: 130
RY, q[0], -3.14159265, time: 130.0
RY, q[2], -3.14159265, time: 130.0
RY, q[0], -3.14159265, time: 150.0
RY, q[2], -3.14159265, time: 150.0
CZ, q[2], q[2], time: 160
RY, q[0], -3.14159265, time: 170.0
RY, q[2], -3.14159265, time: 170.0
RY, q[5], -1.57079633, time: 190
RY, q[0], -3.14159265, time: 190.0
RY, q[2], -3.14159265, time: 190.0
RY, q[0], -3.14159265, time: 210.0
RY, q[2], -3.14159265, time: 210.0
CZ, q[2], q[2], time: 220
RX, q[0], -3.14159265, time: 230.0
RY, q[5], 1.57079633, time: 250
CZ, q[2], q[2], time: 280
RX, q[0], -0.785398163, time: 330
RY, q[2], 1.57079633, time: 330
CZ, q[2], q[2], time: 380
RX, q[5], -0.785398163, time: 430
RY, q[5], -1.57079633, time: 450
RY, q[2], -1.57079633, time: 450
CZ, q[5], q[5], time: 480
RX, q[2], 0.785398163, time: 530
CZ, q[5], q[5], time: 580
RY, q[2], 1.57079633, time: 610
RY, q[5], -1.57079633, time: 610
CZ, q[2], q[2], time: 640
RY, q[5], 1.57079633, time: 670
RY, q[2], -1.57079633, time: 670
CZ, q[5], q[5], time: 700
RX, q[0], 0.785398163, time: 750
RY, q[2], 1.57079633, time: 770
CZ, q[2], q[2], time: 800
RY, q[5], -1.57079633, time: 830
CZ, q[2], q[2], time: 860
CZ, q[2], q[2], time: 900
RY, q[5], 1.57079633, time: 930
RY, q[2], -1.57079633, time: 930
CZ, q[5], q[5], time: 960
RX, q[0], -0.785398163, time: 1010
RY, q[2], 1.57079633, time: 1030
CZ, q[2], q[2], time: 1060
RY, q[5], -1.57079633, time: 1090
CZ, q[2], q[2], time: 1120
RY, q[2], 1.57079633, time: 1150
RX, q[2], -0.785398163, time: 1170
CZ, q[2], q[2], time: 1220
RY, q[5], 1.57079633, time: 1250
RY, q[2], -1.57079633, time: 1250
CZ, q[5], q[5], time: 1280
RX, q[0], 0.785398163, time: 1330
RY, q[2], 1.57079633, time: 1350
CZ, q[2], q[2], time: 1380
RY, q[3], -1.57079633, time: 1410
RY, q[6], -1.57079633, time: 1410
CZ, q[3], q[3], time: 1440
RY, q[5], -1.57079633, time: 1450
CZ, q[2], q[2], time: 1480
RY, q[3], -1.57079633, time: 1490
RY, q[6], 1.57079633, time: 1510
RY, q[2], 1.57079633, time: 1510
RX, q[2], -0.785398163, time: 1530
CZ, q[6], q[6], time: 1540
RY, q[2], -1.57079633, time: 1550
CZ, q[2], q[2], time: 1580
RY, q[3], 1.57079633, time: 1610
RY, q[6], -1.57079633, time: 1610
CZ, q[3], q[3], time: 1640
RY, q[5], 1.57079633, time: 1650
RY, q[2], -1.57079633, time: 1650
CZ, q[5], q[5], time: 1680
RY, q[2], 1.57079633, time: 1710
RY, q[6], 1.57079633, time: 1710
CZ, q[2], q[2], time: 1740
RY, q[5], -1.57079633, time: 1770
CZ, q[2], q[2], time: 1800
RX, q[0], -0.785398163, time: 1850
RY, q[2], 1.57079633, time: 1850
CZ, q[2], q[2], time: 1900
RY, q[5], 1.57079633, time: 1930
RY, q[2], -1.57079633, time: 1930
CZ, q[5], q[5], time: 1960
RX, q[2], 0.785398163, time: 2010
CZ, q[5], q[5], time: 2060
RX, q[0], 0.785398163, time: 2110
RY, q[2], 1.57079633, time: 2130
RY, q[0], 1.57079633, time: 2130
CZ, q[2], q[2], time: 2160
RY, q[0], 1.57079633, time: 2190
RY, q[2], -1.57079633, time: 2190
CZ, q[0], q[0], time: 2220
RY, q[2], 1.57079633, time: 2250
CZ, q[5], q[5], time: 2280
RY, q[0], -1.57079633, time: 2310
CZ, q[2], q[2], time: 2340
RX, q[2], -0.785398163, time: 2390
RY, q[0], 1.57079633, time: 2410
CZ, q[0], q[0], time: 2440
RX, q[2], 0.785398163, time: 2490
CZ, q[5], q[5], time: 2540
RY, q[0], 1.57079633, time: 2570
RX, q[0], -0.785398163, time: 2590
CZ, q[0], q[0], time: 2640
RY, q[2], 1.57079633, time: 2670
RY, q[5], -1.57079633, time: 2670
CZ, q[2], q[2], time: 2700
RY, q[5], 1.57079633, time: 2730
RY, q[6], 1.57079633, time: 2730

Notice that qsoverlay somehow decided to ignore the position of my X and Y gates. Apparently then, this is another instance of the issue I filed before (#18) , where the prepz gates would suffer from a wrong timestamp issue.

I checked, and the error is already present before b.finalize() is called: the X and Y gates already have an incorrect timing before this.

Astlaan commented 4 years ago

Ok, I think I found the error. I made some changes and the gates are now introduced with the correct time in builder.py.

The problem was that some gate functions (X_gate, Y_gate,Z_gate, had_from_rot, CNOT_from_CZ, CRX_from_CZ) were incorrectly defined in qsoverlay/gate_functions.py. These functions receive time as argument, but don't pass it to builder when using the < (__lt__) operator.

A fix possibility would be to pass a dictionary (kwargs) instead of unfolding it (**kwargs) to these gate_functions. And to only unfold the dictionary in the __lt__function. However, I think that might require changes in many places in the code, since the < operator is also used in other parts of qsoverlay...

An easier fix is probably to just modify __lt__ so that it can receive a tuple with an extra parameter, in such a way that it does not conflict with the return_flag functionality; and add the time parameter to the tuples in the gate_functions. This will at least fix the time parameter usage when building circuits (though it will not fix the other usages of < outside of qsoverlay/gate_functions.py.

The ltoperator is also not prepared to receive such a time argument through the gate_desc list.

Astlaan commented 4 years ago

Made a pull request #20 in order to solve this.