quil-lang / quilc

The optimizing Quil compiler.
Apache License 2.0
452 stars 73 forks source link

A violent error via quil_to_native_quil on ARM64 #842

Closed genos closed 1 year ago

genos commented 1 year ago

Hello, quilc wizards! I've caused an interesting crash on ARM64.

In order to get quilc to compile on ARM64, I had to hack on cffi a little bit, so perhaps I've screwed something up there? Anyway, when trying to compile "random-ish but architecture-respecting" circuit à la quanvolutional neural networks for running on either of Rigetti's current QPU offerings, I run into "a violent error" (see below). I think it's raised in find-diagonalizer-in-e-basis via compress-instructions-in-context, but I bow to your knowledge and expertise.

Thanks!

$ quilc --version
1.26.0 [0561b21]
$ quilc -P -S
+-----------------+
|  W E L C O M E  |
|   T O   T H E   |
|  R I G E T T I  |
|     Q U I L     |
| C O M P I L E R |
+-----------------+
Copyright (c) 2016-2020 Rigetti Computing.

<134>1 2022-09-01T14:27:18Z quilc 2216084 LOG0001 - Launching quilc.
<134>1 2022-09-01T14:27:18Z quilc 2216084 - - Spawning server at (tcp://*:5555) .

<134>1 2022-09-01T14:31:54Z quilc 2216084 - - Request 335caf44-0127-49fd-af85-d749589d6696 received for get_version_info
<134>1 2022-09-01T14:31:54Z quilc 2216084 LOG0002 [rigetti@0000 methodName="get_version_info" requestID="335caf44-0127-49fd-af85-d749589d6696" wallTime="0.354" error="false"] Requested get_version_info completed
<134>1 2022-09-01T14:31:54Z quilc 2216084 - - Request 21f40f23-71b5-4e76-97b8-5646219c3736 received for quil_to_native_quil
A violent error occurred when compressing a subsequence.
The offending subsequence is:
RX(-1.5707963267948966) 24
RZ(1.5707963267948966) 24
XY(3.141592653589793) 23 24
RX(1.5707963267948966) 23
RZ(-1.5707963267948966) 23
RX(-1.5707963267948966) 23
XY(3.141592653589793) 23 24
RZ(3.141592653589793) 23
RZ(1.2358574342722735) 24
RX(-1.5707963267948966) 24
RZ(1.5707963267948966) 22
RX(1.5707963267948966) 22
The current compression context is:
#S(CL-QUIL::COMPILATION-CONTEXT :AQVM #S(CL-QUIL::ANTISOCIAL-QVM :WFS #(NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED) :INTERNAL-INDICES #(NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED)) :CHIP-SPECIFICATION NIL)<131>1 2022-09-01T14:32:00Z quilc 2216084 LOG0002 [rigetti@0000 methodName="quil_to_native_quil" requestID="21f40f23-71b5-4e76-97b8-5646219c3736" wallTime="5.308" error="true"] Request 21f40f23-71b5-4e76-97b8-5646219c3736 error: Unhandled error in host program:
Could not find diagonalizer for matrix
#<MATRIX/COMPLEX-DOUBLE-FLOAT (4x4):
   0.770 - 0.637j     0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.770 - 0.637j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.770 - 0.637j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j    -0.482 + 0.876j>
after 16 attempts.
notmgsk commented 1 year ago

Would you be able to share a minimal program that reproduces the issue?

genos commented 1 year ago

@notmgsk It's not exactly minimal, but here's the circuit that caused the above error in a quil_to_native_quil call. I'll see if I can shrink it down to something that still fails.

Edit: though of course now that I've posted this, it seems to compile without issue 🤔

RESET
DECLARE ro BIT[16]
DECLARE data REAL[16]
RX(data[0]) 130
RX(data[1]) 131
RX(data[2]) 36
RX(data[3]) 37
RX(data[4]) 134
RX(data[5]) 133
RX(data[6]) 132
RX(data[7]) 10
RX(data[8]) 11
RX(data[9]) 113
RX(data[10]) 21
RX(data[11]) 22
RX(data[12]) 23
RX(data[13]) 24
RX(data[14]) 25
RX(data[15]) 26
CNOT 133 132
RY(4.19482383116228) 37
RY(2.840807509857065) 131
CNOT 10 113
CNOT 133 132
RZ(4.0565033608709715) 130
RY(1.9092177695081511) 23
RZ(2.340683690103788) 25
RZ(5.55242533201432) 131
RX(0.8099487146493436) 22
RZ(1.8731928137076723) 133
RY(5.521458835494046) 132
RZ(4.181033757350933) 131
RX(4.454195379991254) 25
RZ(5.699670434878575) 37
CNOT 23 24
CNOT 134 133
CNOT 11 26
CNOT 134 133
CNOT 36 37
RZ(3.738681461837271) 21
RX(3.5183644426139913) 37
RY(3.250663696787094) 26
RY(1.2358574342722735) 24
CNOT 22 23
RX(4.615907256294149) 11
RY(5.799889969180385) 24
CNOT 36 37
RY(2.839267311861715) 36
CNOT 24 25
RX(4.165108156329006) 130
RY(1.6582952459554838) 131
CNOT 23 24
CNOT 130 131
RX(0.41599743341366646) 37
RY(4.48858872597822) 130
RX(1.5371972532629856) 21
RX(4.370259155914811) 134
RX(4.246403576074984) 10
RY(2.7255253078722346) 22
RX(4.986989535781094) 26
CNOT 130 131
RX(4.615384969894928) 23
RY(4.141237000824283) 25
RZ(3.9279636066767476) 26
RX(1.4023941233378947) 21
RY(5.374800347750356) 133
RX(0.7163566756582871) 113
RX(0.0844372455168249) 130
RZ(3.396332392156367) 130
CNOT 21 22
RZ(1.7688789368156994) 22
CNOT 130 131
CNOT 130 131
RZ(5.028876773076453) 113
RY(3.044000324954975) 133
RY(2.9616418172886907) 24
RX(1.879489328553943) 37
CNOT 134 133
CNOT 11 26
RY(5.9137257002957915) 11
RX(1.2150493862443377) 133
RY(1.555672373003021) 133
RX(5.597764312349765) 36
CNOT 133 132
RX(5.1646582671368915) 130
RY(4.832845979525608) 23
RX(3.7342661697365873) 26
CNOT 36 21
RY(4.3067408847458815) 22
RY(5.4310085142869555) 134
CNOT 134 133
RX(2.388301670194917) 11
RY(4.506150692846598) 23
RZ(3.141674780606929) 26
RZ(1.6128100054016081) 10
CNOT 130 131
CNOT 37 134
RX(3.077517540154005) 130
CNOT 131 132
CNOT 37 134
RY(4.449178691901883) 130
RX(3.135828708789536) 134
RY(2.8503385622066655) 26
CNOT 36 21
RY(5.878734028669498) 36
RX(6.038308303837545) 36
RY(5.453794248283926) 134
RY(2.5878422138925306) 134
CNOT 130 131
CNOT 23 24
RX(5.394240758256413) 25
RZ(5.80376291201709) 24
MEASURE 130 ro[0]
MEASURE 131 ro[1]
MEASURE 36 ro[2]
MEASURE 37 ro[3]
MEASURE 134 ro[4]
MEASURE 133 ro[5]
MEASURE 132 ro[6]
MEASURE 10 ro[7]
MEASURE 11 ro[8]
MEASURE 113 ro[9]
MEASURE 21 ro[10]
MEASURE 22 ro[11]
MEASURE 23 ro[12]
MEASURE 24 ro[13]
MEASURE 25 ro[14]
MEASURE 26 ro[15]
genos commented 1 year ago

Ok, I've got another failing example, this time on Aspen-11. Some traceback is snipped for brevity &/or IP concerns:

Python traceback:

  File "<SNIP>/.venv/lib/python3.8/site-packages/pyquil/api/_abstract_compiler.py", line 123, in quil_to_native_quil
    response = self._compiler_client.compile_to_native_quil(request)
  File "<SNIP>/.venv/lib/python3.8/site-packages/pyquil/api/_compiler_client.py", line 188, in compile_to_native_quil
    response: rpcq.messages.NativeQuilResponse = rpcq_client.call(
  File "<SNIP>/.venv/lib/python3.8/site-packages/rpcq/_client.py", line 205, in call
    raise utils.RPCError(reply.error)                                                                                                                                                                           rpcq._utils.RPCError: Unhandled error in host program:
Could not find diagonalizer for matrix
#<MATRIX/COMPLEX-DOUBLE-FLOAT (4x4):
   0.730 - 0.684j     0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.730 + 0.684j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.686 - 0.727j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j     0.686 + 0.727j>
after 16 attempts.

quilc messages:

<134>1 2022-09-01T15:42:58Z quilc 2219005 - - Request f18cd747-4896-45a6-a332-94feb6a14a34 received for quil_to_native_quil
A violent error occurred when compressing a subsequence.
The offending subsequence is:
RZ(6.880274115427064) 46
RX(1.5707963267948966) 46
RZ(1.5707963267948966) 46                                                                                                                                                                                       RX(-1.5707963267948966) 46                                                                                                                                                                                      CPHASE(3.141592653589793) 46 45                                                                                                                                                                                 RZ(3.141592653589793) 45                                                                                                                                                                                        RX(1.5707963267948966) 46                                                                                                                                                                                       RZ(-1.5707963267948966) 46                                                                                                                                                                                      RX(-1.5707963267948966) 46                                                                                                                                                                                      The current compression context is:                                                                                                                                                                             #S(CL-QUIL::COMPILATION-CONTEXT :AQVM #S(CL-QUIL::ANTISOCIAL-QVM :WFS #(NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED) :INTERNAL-INDICES #(NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED)) :CHIP-SPECIFICATION #<CHIP-SPECIFICATION of 48:45 objects>)<131>1 2022-09-01T15:43:00Z quilc 2219005 LOG0002 [rigetti@0000 methodName="quil_to_native_quil" requestID="f18cd747-4896-45a6-a332-94feb6a14a34" wallTime="2.111" error="true"] Request f18cd747-4896-45a6-a332-94feb6a14a34 error: Unhandled error in host program:
Could not find diagonalizer for matrix                                                                                                                                                                          #<MATRIX/COMPLEX-DOUBLE-FLOAT (4x4):
   0.707 - 0.707j     0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.707 - 0.707j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.707 - 0.707j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j    -0.707 + 0.707j>
after 16 attempts.

Offending (again, long, sorry, I'll try to shorten this) program:

RESET
DECLARE ro BIT[15]
DECLARE data REAL[15]
RX(data[0]) 32
RX(data[1]) 33
RX(data[2]) 34
RX(data[3]) 35
RX(data[4]) 36
RX(data[5]) 37
RX(data[6]) 42
RX(data[7]) 43
RX(data[8]) 44
RX(data[9]) 45
RX(data[10]) 46
RX(data[11]) 47
RX(data[12]) 21
RX(data[13]) 30
RX(data[14]) 31
CNOT 36 37
RY(4.19482383116228) 34
RY(2.840807509857065) 33
CNOT 37 30
CNOT 36 37
RZ(4.0565033608709715) 32
RY(1.9092177695081511) 47
RZ(2.340683690103788) 30
RZ(5.55242533201432) 33
RX(0.8099487146493436) 46
RZ(1.8731928137076723) 37
RY(5.521458835494046) 42
RZ(4.181033757350933) 33
RX(4.454195379991254) 30
RZ(5.699670434878575) 35
CNOT 46 31
CNOT 35 36
CNOT 43 44
CNOT 36 21
CNOT 33 34
RZ(3.738681461837271) 46
RX(3.5183644426139913) 34
RY(3.250663696787094) 31
RY(1.2358574342722735) 30
CNOT 45 46
RX(4.615907256294149) 44
RY(5.799889969180385) 21
CNOT 33 34
RY(2.839267311861715) 33
CNOT 46 47
RX(4.165108156329006) 32
RY(1.6582952459554838) 33
CNOT 46 31
CNOT 32 31
RX(0.41599743341366646) 35
RY(4.48858872597822) 32
RX(1.5371972532629856) 45
RX(4.370259155914811) 36
RX(4.246403576074984) 43
RY(2.7255253078722346) 46
RX(4.986989535781094) 31
CNOT 32 31
RX(4.615384969894928) 47
RY(4.141237000824283) 30
RZ(3.9279636066767476) 31
RX(1.4023941233378947) 45
RY(5.374800347750356) 37
RX(0.7163566756582871) 45
RX(0.0844372455168249) 32
RZ(3.396332392156367) 32
CNOT 44 45
RZ(1.7688789368156994) 47
CNOT 32 31
CNOT 32 31
RZ(5.028876773076453) 44
RY(3.044000324954975) 37
RY(2.9616418172886907) 21
RX(1.879489328553943) 35
CNOT 35 36
CNOT 42 43
RY(5.9137257002957915) 44
RX(1.2150493862443377) 37
RY(1.555672373003021) 37
RX(5.597764312349765) 34
CNOT 36 37
RX(5.1646582671368915) 32
RY(4.832845979525608) 21
RX(3.7342661697365873) 31
CNOT 32 45
RY(4.3067408847458815) 46
RY(5.4310085142869555) 35
CNOT 35 36
RX(2.388301670194917) 44
RY(4.506150692846598) 47
RZ(3.141674780606929) 31
RZ(1.6128100054016081) 43
CNOT 32 31
CNOT 35 36
RX(3.077517540154005) 32
CNOT 32 33
CNOT 34 35
RY(4.449178691901883) 32
RX(3.135828708789536) 36
RY(2.8503385622066655) 31
CNOT 32 45
RY(5.878734028669498) 34
RX(6.038308303837545) 34
MEASURE 32 ro[0]
MEASURE 33 ro[1]
MEASURE 34 ro[2]
MEASURE 35 ro[3]
MEASURE 36 ro[4]
MEASURE 37 ro[5]
MEASURE 42 ro[6]
MEASURE 43 ro[7]
MEASURE 44 ro[8]
MEASURE 45 ro[9]
MEASURE 46 ro[10]
MEASURE 47 ro[11]
MEASURE 21 ro[12]
MEASURE 30 ro[13]
MEASURE 31 ro[14]
genos commented 1 year ago

It's not happening reliably, but the following (deleted as much as I could from the above that didn't touch qubits 32, 45, or 46) crashes most of the time with the same violent error:

RESET
DECLARE ro BIT[15]
DECLARE data REAL[15]
RX(data[0]) 32
RX(data[2]) 34
RX(data[5]) 37
RX(data[6]) 42
RX(data[7]) 43
RX(data[9]) 45
RX(data[10]) 46
RZ(4.0565033608709715) 32
RX(0.8099487146493436) 46
RZ(3.738681461837271) 46
CNOT 45 46
RX(4.165108156329006) 32
RY(4.48858872597822) 32
RX(1.5371972532629856) 45
RY(2.7255253078722346) 46
RX(1.4023941233378947) 45
RX(0.7163566756582871) 45
RX(0.0844372455168249) 32
RZ(3.396332392156367) 32
RX(5.1646582671368915) 32
CNOT 32 45
RY(4.3067408847458815) 46
RX(3.077517540154005) 32
RY(4.449178691901883) 32
CNOT 32 45
MEASURE 32 ro[0]
MEASURE 33 ro[1]
MEASURE 34 ro[2]
MEASURE 35 ro[3]
MEASURE 36 ro[4]
MEASURE 37 ro[5]
MEASURE 42 ro[6]
MEASURE 43 ro[7]
MEASURE 44 ro[8]
MEASURE 45 ro[9]
MEASURE 46 ro[10]
MEASURE 47 ro[11]
MEASURE 21 ro[12]
MEASURE 30 ro[13]

Here's the quilc complaint:

A violent error occurred when compressing a subsequence.
The offending subsequence is:
RX(-1.5707963267948966) 46
RZ(2.1678851350423747) 46
RX(1.5707963267948966) 46
RZ(1.5707963267948966) 46
RX(-1.5707963267948966) 46
CPHASE(3.141592653589793) 46 45
RZ(4.71238898038469) 45
RX(1.5707963267948966) 46
RZ(5.4614698658232195) 46
RX(1.5707963267948966) 45
RZ(3.655948052259167) 45
RX(-1.5707963267948966) 46
RX(-1.5707963267948966) 45
RZ(-1.5707963267948966) 45
RX(1.5707963267948966) 45
RZ(1.5707963267948966) 45
RX(-1.5707963267948966) 45
The current compression context is:
#S(CL-QUIL::COMPILATION-CONTEXT :AQVM #S(CL-QUIL::ANTISOCIAL-QVM :WFS #(NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED) :INTERNAL-INDICES #(NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED)) :CHIP-SPECIFICATION NIL)<131>1 2022-09-01T16:12:56Z quilc 2220818 LOG0002 [rigetti@0000 methodName="quil_to_native_quil" requestID="3e1182a7-756f-4089-a230-a47556ed042b" wallTime="0.401" error="true"] Request 3e1182a7-756f-4089-a230-a47556ed042b error: Unhandled error in host program:
Could not find diagonalizer for matrix
#<MATRIX/COMPLEX-DOUBLE-FLOAT (4x4):
   0.707 - 0.707j     0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.707 - 0.707j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.707 - 0.707j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j    -0.707 + 0.707j>
after 16 attempts.
stylewarning commented 1 year ago

Is this happening on ARM only?

I find that this function is pretty sensitive to the underlying numerical libraries. I myself was experimenting with changing the eigenvalue function and was getting the same failures when doing so. Unfortunately I didn't dig deep enough to truly find out why.

One thing we could try to do is replace this function wholesale with a more direct approach a la #841.

genos commented 1 year ago

So far it is only failing on ARM; the compilation succeeds on x86.

I did see #841 on the issues list when I started this post and thought I'd been scooped! Regarding

If we want to implement this in QUILC, we'll need to get qz into MAGICL.

Would that be a long and laborious process?

stylewarning commented 1 year ago

Would that be a long and laborious process?

I think the labor would be measured in hours. It would consist of:

  1. Finding the right LAPACK function (that we already have a binding for). [minutes]
  2. Making a valid example call to that function from Lisp. [sub-hour]
  3. Making a nice wrapper according to MAGICL's discipline for high-level bindings. [sub-hour]
  4. Testing it. [hour?]
  5. Using it to implement the Python function proof-of-concept in the issue. [minutes]
  6. Slotting it in to where the current diagonalizer function is [minutes to hours, depending on familiarity]
  7. Testing QUILC with it. [minutes]
  8. Debugging. [hours?]
genos commented 1 year ago

For another piece of information, here's what happened when trying to run make test in a fresh copy of the QUILC repo on the aforementioned ARM64 machine:

CL-QUIL-TESTS (Suite)
  TEST-LOGICAL-MATRIX-SANITY
    I 0
    X 0
    Y 0
    Z 0
    X 0;X 0;
    I 0;I 1;
    CNOT 0 1
    CNOT 1 0
    X 0;CNOT 0 1;
    X 0;CNOT 1 0;
    PHASE(pi/2) 0
    PHASE(-pi/2) 0
    DAGGER PHASE(pi/2) 0
    DAGGER DAGGER PHASE(pi/2) 0
    CONTROLLED X 0 1
    CONTROLLED X 1 0
    CONTROLLED Y 0 1
    CONTROLLED Y 1 0
    CONTROLLED DAGGER PHASE(pi/2) 1 0
    DAGGER CONTROLLED PHASE(pi/2) 1 0
    FORKED Y 0 1
    FORKED Y 1 0
    FORKED PHASE(pi, pi/2) 1 0
    FORKED PHASE(pi/2, pi) 1 0
    CONTROLLED FORKED Y 2 1 0
    FORKED CONTROLLED Y 1 2 0
    FORKED CONTROLLED Y 2 1 0
    CONTROLLED FORKED Y 1 2 0
    CONTROLLED FORKED DAGGER PHASE(pi, pi/2) 2 1 0
    CONTROLLED DAGGER FORKED PHASE(pi, pi/2) 2 1 0
    DAGGER CONTROLLED FORKED PHASE(pi, pi/2) 2 1 0
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(-0.18814283931458675d0 0.9821416761418109d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.8858847048412424d0 -0.46390547499285345d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(-0.9996593735204952d0 -0.0260986002040574d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.9353437693392024d0 -0.3537400643952177d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.7586914619625825d0 -0.6514501251401211d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(-0.5951714439976432d0 -0.8035987507766299d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(-0.14727810051260104d0 -0.9890951223767107d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.990712986842873d0 0.13596976759880508d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(-0.9984863885895177d0 0.05499938000980359d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.9384603532099609d0 0.3453869792754724d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.521114478011301d0 -0.8534867900600508d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.6033112725160329d0 -0.79750580465291d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.6437102151102836d0 -0.7652693375293907d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(-0.9919904995901759d0 -0.12631250422200063d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.6722738237147248d0 -0.740302577293895d0)
WARNING:
   Complex determinant found for a matrix expected to be (real) orthogonal: det=#C(0.6220142429768358d0 -0.7830059268830307d0)
Unhandled QUIL::DIAGONALIZER-NOT-FOUND in thread #<SB-THREAD:THREAD "main thread" RUNNING
                                                    {10027CAD03}>:
  Could not find diagonalizer for matrix
#<MATRIX/COMPLEX-DOUBLE-FLOAT (4x4):
   1.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     1.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.924 + 0.383j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j     0.924 - 0.383j>
after 16 attempts.
genos commented 1 year ago

In summary, I don't know what's going on

I'm well and truly flummoxed at this point. Per a suggestion out-of-band, I attempted running the diagonalization routine and comparing both the # attempts and the residuals (largest absolute values of the off-diagonal entries of the matrix $D$ that should be diagonal and of the difference between $ODO^T$ and $UU^T$) for (admittedly slightly modified copy-pasta versions of, so maybe I made a mistake there) the Python and Lisp implementations. The versions yield similar results on all three platforms (my laptop, an x86 box, and the ARM box in question): all tries worked after the first attempt, and all residuals were effectively zero.

LAPACK details on the three platforms

Platform LAPACK Installed via
Apple Laptop (Intel) liblapack.3.10.1.dylib brew install lapack
x86 liblapack-dev version 3.7.1-4ubuntu1 apt-get install liblapack-dev
ARM liblapack-dev version 3.9.0-1build1 apt-get install liblapack-dev

Python attempts:

python_attempts

Python residuals:

python_residuals

Lisp attempts:

lisp_attempts

Lisp residuals:

lisp_residuals

Supporting files

Python script gather_data.py ```python from typing import NamedTuple import numpy as np import pandas as pd from scipy.stats import unitary_group import typer class _Decomp(NamedTuple): attempts: int eigvals: np.ndarray eigvecs: np.ndarray def _orthogonal_diagonalization(m: np.ndarray, rng: np.random.Generator) -> _Decomp: """github.com/gecrooks/quantumflow-dev/blob/master/quantumflow/decompositions.py#L325""" for i in range(16): c = rng.uniform(0, 1) matrix = c * m.real + (1 - c) * m.imag _, eigvecs = np.linalg.eigh(matrix) eigvals = eigvecs.T @ m @ eigvecs if np.allclose(m, eigvecs @ eigvals @ eigvecs.T): return _Decomp(attempts=i, eigvals=eigvals, eigvecs=eigvecs) raise np.linalg.LinAlgError("Matrix is not orthogonally diagonalizable") class _Datum(NamedTuple): attempts: int max_off_diagonal: float max_difference: float def _collect(u: np.ndarray, rng: np.random.Generator) -> _Datum: uut = u @ u.T decomp = _orthogonal_diagonalization(uut, rng) d, o = decomp.eigvals, decomp.eigvecs m = o.T @ uut @ o return _Datum( attempts=decomp.attempts, max_off_diagonal=np.abs(m - np.diag(np.diag(m))).max(), max_difference=np.abs(o @ d @ o.T - uut).max(), ) def collect_specifics(_iterations: int, rng: np.random.Generator) -> pd.Series: residuals = [] for unitary in [ np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]]), np.diag([1, 1, 1, 1j]), np.kron(np.eye(2), 1 / np.sqrt(2) * np.array([[1, -1j], [-1j, 1]])), np.array( [ [-0.965 + 0.133j, 0.093 + 0.000j, -0.000 + 0.000j, -0.000 + 0.206j], [0.093 + 0.000j, 0.965 + 0.133j, 0.000 - 0.206j, -0.000 + 0.000j], [-0.000 + 0.000j, 0.000 - 0.206j, 0.965 - 0.133j, -0.093 + 0.000j], [0.000 + 0.206j, -0.000 + 0.000j, -0.093 + 0.000j, -0.965 - 0.133j], ] ), ]: residuals.append(_collect(unitary, rng)) return pd.Series(residuals) def collect_su4(iterations: int, rng: np.random.Generator) -> pd.Series: residuals = [] gen = unitary_group(dim=4, seed=rng.integers(1 << 32)) for _ in range(iterations): residuals.append(_collect(gen.rvs(), rng)) return pd.Series(residuals) def collect_su2_x_su2(iterations: int, rng: np.random.Generator) -> pd.Series: residuals = [] gen = unitary_group(dim=2, seed=rng.integers(1 << 32)) for _ in range(iterations): residuals.append(_collect(np.kron(gen.rvs(), gen.rvs()), rng)) return pd.Series(residuals) def main( iterations: int = typer.Option(10_000, help="Number of rounds to run"), seed: int = typer.Option(96692877, help="Seed for PRNG (random.org)"), platform: str = typer.Option("laptop", help="Platform collected on"), ): rng = np.random.default_rng(seed) collections = [] for (name, func) in [ ("Specifics", collect_specifics), ("SU(4)", collect_su4), ("SU(2)xSU(2)", collect_su2_x_su2), ]: for d in func(iterations, rng): collections.append( { "name": name, "attempts": d.attempts, "max_off_diagonal": d.max_off_diagonal, "max_difference": d.max_difference, } ) df = pd.DataFrame(collections) df["platform"] = platform df.to_feather(f"{platform}_python.arrow") if __name__ == "__main__": typer.run(main) ```
Lisp script gather-details.lisp ```lisp ;;;; sbcl --load gather-data.lisp --eval "(sb-ext:save-lisp-and-die \"gather-data\" :executable t :save-runtime-options t :toplevel 'gather-data:toplevel)" ;;;; ./gather-data -p PLATFORM ;;;; ;;;; Thanks https://stevelosh.com/blog/2021/03/small-common-lisp-cli-programs/ (eval-when (:compile-toplevel :load-toplevel :execute) (ql:quickload '(:adopt :alexandria :magicl) :silent t)) (defpackage :gather-data (:use :cl) (:export :toplevel :*ui*)) (in-package :gather-data) (defconstant +dtype+ '(complex double-float)) ;;;; Modified copy-pasta from quilc ;; https://github.com/quil-lang/quilc/blob/master/src/frontend-utilities.lisp#L161 (defconstant +double-comparison-threshold-loose+ 1d-5) (defconstant +double-comparison-threshold-strict+ 5d-11) (defun double~ (x y) (let ((diff (abs (- x y)))) (< diff +double-comparison-threshold-loose+))) (defun double= (x y) (let ((diff (abs (- x y)))) (< diff +double-comparison-threshold-strict+))) ;; https://github.com/quil-lang/quilc/blob/master/src/matrix-operations.lisp#L143 (defun orthonormalize-matrix! (x) (declare (optimize speed)) (let ((nrows (magicl:nrows x)) (ncols (magicl:ncols x))) (declare (type alexandria:array-length nrows ncols)) (when (or (zerop nrows) (zerop ncols)) (return-from orthonormalize-matrix! x)) (labels ((column-norm (m col) (let ((n^2 (dot-columns m col m col))) (assert (not (double= 0.0d0 n^2))) (sqrt n^2))) (normalize-column! (m col) (let ((norm (column-norm m col))) (dotimes (row nrows) (setf (magicl:tref m row col) (/ (magicl:tref m row col) norm))))) (assign-column! (a b col) ;; a[:,col] = b[:,col] (dotimes (i nrows) (setf (magicl:tref a i col) (magicl:tref b i col)))) (dot-columns (a p b q) (loop :for i :below nrows :sum (* (conjugate (magicl:tref a i p)) (magicl:tref b i q))))) (let ((v (magicl:deep-copy-tensor x)) (q (magicl:zeros (list nrows ncols) :type (magicl:element-type x)))) (loop :for j :below ncols :do (assign-column! q v j) (normalize-column! q j) (loop :for k :from (1+ j) :below ncols :do (let ((s (dot-columns q j v k))) (loop :for row :below nrows :do (decf (magicl:tref v row k) (* s (magicl:tref q row j))))))) q)))) ;; https://github.com/quil-lang/quilc/blob/master/src/compilers/approx.lisp#L158 (defun ensure-positive-determinant (m) (let ((d (magicl:det m))) (if (double= -1d0 (realpart d)) (magicl:@ m (magicl:from-diag (list -1 1 1 1) :type +dtype+)) m))) (defconstant +diagonalizer-max-attempts+ 16) (defun diagonalizer-number-generator (k) (abs (sin (/ k 10.0d0)))) (defun orthogonal-diagonalization (uut) (loop :for attempt :from 0 :below +diagonalizer-max-attempts+ :do (let* ((coeff (diagonalizer-number-generator attempt)) (matrix (magicl:map (lambda (z) (+ (* coeff (realpart z)) (* (- 1 coeff) (imagpart z)))) uut)) (evecs (ensure-positive-determinant (orthonormalize-matrix! (nth-value 1 (magicl:eig matrix))))) (evals (magicl:from-diag (magicl:diag (magicl:@ (magicl:transpose evecs) uut evecs)))) (reconstructed (magicl:@ evecs evals (magicl:transpose evecs)))) (when (and (double= 1.0d0 (magicl:det evecs)) (magicl:every #'double= uut reconstructed) (magicl:every #'double~ (magicl:eye 4 :type +dtype+) (magicl:@ (magicl:transpose evecs) evecs))) (return-from orthogonal-diagonalization (list attempt evals evecs))))) (list +diagonalizer-max-attempts+)) ;;;; Functionality (defconstant +nan+ "NAN") (defun max-abs-diff (a b) (loop :for z :across (magicl::storage (magicl:.- a b)) :maximize (abs z))) (defun collect (u) (let* ((uut (magicl:@ u (magicl:transpose u))) (decomp (orthogonal-diagonalization uut))) (if (< (first decomp) +diagonalizer-max-attempts+) (destructuring-bind (attempts d o) decomp (let* ((m (magicl:@ (magicl:transpose o) uut o)) (max-off-diagonal (max-abs-diff m (magicl:from-diag (magicl:diag m)))) (max-difference (max-abs-diff (magicl:@ o d (magicl:transpose o)) uut))) (list attempts max-off-diagonal max-difference))) (list +diagonalizer-max-attempts+ +nan+ +nan+)))) (defun report (u name platform stream) (destructuring-bind (attempts max-off-diagonal max-difference) (collect u) (format stream "~{~A~^,~}~%" (list name attempts (substitute #\e #\d (format nil "~A" max-off-diagonal)) (substitute #\e #\d (format nil "~A" max-difference)) platform)))) (defconstant +specifics+ (let* ((i (complex 0d0 1d0)) (-i (complex 0d0 -1d0)) (1/sqrt2 (/ (sqrt 2d0))) (-i/sqrt2 (* -i 1/sqrt2))) (list (magicl:from-list '(1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0) '(4 4) :type +dtype+) (magicl:from-diag (list 1 1 1 i) :type +dtype+) (magicl:kron (magicl:eye 2 :type +dtype+) (magicl:from-list (list 1/sqrt2 -i/sqrt2 -i/sqrt2 1/sqrt2) '(2 2) :type +dtype+))))) (defconstant +iterations+ 1000) (defun run (platform) (let ((filename (format nil "~A_lisp.csv" platform))) (with-open-file (stream filename :direction :output :if-exists :supersede) (loop :for u :in +specifics+ :do (report u "Specifics" platform stream)) (loop :repeat +iterations+ :for u = (magicl:random-unitary 4) :then (magicl:random-unitary 4) :do (report u "SU(4)" platform stream)) (loop :repeat +iterations+ :for u = (magicl:kron (magicl:random-unitary 2) (magicl:random-unitary 2)) :then (magicl:kron (magicl:random-unitary 2) (magicl:random-unitary 2)) :do (report u "SU(2)xSU(2)" platform stream))))) ;;;; CLI (defparameter *help* (adopt:make-option 'help :help "display help and exit" :long "help" :short #\h :reduce (constantly t))) (defparameter *default-platform* "laptop") (defparameter *platform* (adopt:make-option 'platform :help (format nil "Gather data for PLATFORM (default ~A)" *default-platform*) :long "platform" :short #\p :parameter "PLATFORM" :initial-value *default-platform* :reduce #'adopt:last)) (defparameter *ui* (adopt:make-interface :name "gather-data" :usage "[-p PLATFORM]" :summary "Gather data for the given PLATFORM." :help "Gather data for the given PLATFORM." :contents (list *help* *platform*))) (defun toplevel () (handler-case (multiple-value-bind (arguments options) (adopt:parse-options *ui*) (when (gethash 'help options) (adopt:print-help-and-exit *ui*)) (unless (null arguments) (error "Unrecognized command-line arguments: ~S" arguments)) (run (gethash 'platform options))) (error (c) (adopt:print-error-and-exit c)))) ```
Notebook Diagonalization_Comparison.ipynb (exported to Python) used to generate plots ```python # |Platform| LAPACK | Installed via | # |--|--|--| # |Apple Laptop (Intel) | `liblapack.3.10.1.dylib` | `brew install lapack` | # | x86 | `liblapack-dev` version `3.7.1-4ubuntu1` | `apt-get install liblapack-dev` | # | ARM | `liblapack-dev` version `3.9.0-1build1` | `apt-get install liblapack-dev` | # In[1]: import matplotlib.pyplot as plt import pandas as pd import seaborn as sns sns.set_theme( context="notebook", palette=["#3d3d53", "#00b5ad", "#ef476f"], style="whitegrid", rc={"font.sans-serif": "Open Sans"}, ) platforms = ["laptop", "x86", "arm"] # In[2]: def plot_attempts(df: pd.DataFrame, title: str): g = sns.catplot( df[["name", "attempts", "platform"]], col="name", x="attempts", hue="platform", kind="count", sharey=False, ) g.fig.subplots_adjust(top=0.85) g.fig.suptitle(title) def plot_residuals(df: pd.DataFrame, title): g = sns.catplot( df.melt( id_vars=["name", "platform"], value_vars=[c for c in df.columns if c.startswith("max_")], ), x="name", y="value", col="variable", hue="platform", kind="boxen", ) g.fig.subplots_adjust(top=0.85) g.fig.suptitle(title) for ax in g.fig.axes: ax.set_yscale("log") # In[3]: python = pd.concat([pd.read_feather(f"{p}_python.arrow") for p in platforms]) # In[4]: plot_attempts(python, title="Python Attempts") # In[5]: plot_residuals(python, title="Python Residuals") # In[6]: plot_residuals(python[python.name != "Specifics"], title="Python Residuals") # In[7]: lisp = pd.concat( [pd.read_csv(f"{p}_lisp.csv", names=python.columns) for p in platforms] ) # In[8]: plot_attempts(lisp, title="List Attempts") # In[9]: plot_residuals(lisp, title="Lisp Residuals") # In[10]: plot_residuals(lisp[lisp.name != "Specifics"], title="Lisp Residuals") ```
ecpeterson commented 1 year ago

I'm sorry this has been such a headache. On the bright side, this is an excellent bug report.

notmgsk commented 1 year ago

Here's a super duper lil program that reliably triggers the error:

from pyquil import get_qc, Program

qc = get_qc("4q-qvm")
# qc = get_qc("Aspen-11", as_qvm=True)  # also fails

control = 0
targets = [1, 2, 3]
# targets = [4, 5, 6]  # also fails

p = Program(f"""
CNOT {control} {targets[0]}
CNOT {control} {targets[1]}
CNOT {control} {targets[2]}
""")

e = qc.compile(p)

Doesn't seem to be related the target architecture (e.g. Aspen or fully connected), or to the target qubits. The only restriction seems to be that the control qubit be the same.

genos commented 1 year ago

@notmgsk my hero! Running on the ARM box with quilc --version = 1.26.0 [2b211bb] & qvm --version = 1.17.2 [8e190b7], here's the error message from quilc -P -S when trying to run the above li'l friend:

A violent error occurred when compressing a subsequence.                                                                                                                                                        The offending subsequence is:
RX(1.5707963267948966) 3
RZ(1.5707963267948966) 3                                                                                                                                                                                        RX(-1.5707963267948966) 3
RX(1.5707963267948966) 2
RZ(1.5707963267948966) 2                                                                                                                                                                                        RX(-1.5707963267948966) 2
RZ(3.141592653589793) 0
CZ 2 0                                                                                                                                                                                                          RZ(3.141592653589793) 0
RX(1.5707963267948966) 2
RZ(-1.5707963267948966) 2                                                                                                                                                                                       RX(-1.5707963267948966) 2
CZ 3 0
RZ(3.141592653589793) 0
RX(1.5707963267948966) 3
RX(1.5707963267948966) 0
RZ(-1.5707963267948966) 3
RX(-1.5707963267948966) 3
RZ(0.0) 0
RX(-1.5707963267948966) 0
RZ(0.0) 0
The current compression context is:
#S(CL-QUIL::COMPILATION-CONTEXT :AQVM #S(CL-QUIL::ANTISOCIAL-QVM :WFS #(NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED) :INTERNAL-INDICES #(NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED NOT-SIMULATED)) :
CHIP-SPECIFICATION #<CHIP-SPECIFICATION of 4:6 objects>)<131>1 2022-09-20T15:02:34Z quilc 2397421 LOG0002 [rigetti@0000 methodName="quil_to_native_quil" requestID="c5bf7a64-1bfa-45c8-b8d4-5f88461efe66"
 wallTime="0.582" error="true"] Request c5bf7a64-1bfa-45c8-b8d4-5f88461efe66 error: Unhandled error in host program:
Could not find diagonalizer for matrix
#<MATRIX/COMPLEX-DOUBLE-FLOAT (4x4):
  -0.236 - 0.972j     0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j    -0.236 + 0.972j     0.000 + 0.000j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     1.000 + 0.031j     0.000 + 0.000j
   0.000 + 0.000j     0.000 + 0.000j     0.000 + 0.000j     1.000 - 0.031j>
after 16 attempts.

It also makes a number of complaints (16 to be exact) about Complex determinant found for a matrix expected to be (real) orthogonal.

stylewarning commented 1 year ago

@genos @notmgsk A colleague has an ARM machine and offered to help debug this. So, hopefully within a week or so we'll have time to dig in and see what we can find.

Spin1Half commented 1 year ago

@genos @notmgsk Today @stylewarning and I messed around with this. We did not dig down to find the root cause, but we do have a workaround. LAPACK on ARM seems to only get mad over diagonal matrices, which is a trivial case for find-diagonalizer-in-e-basis, so we just check for diagonal matrices and avoid a LAPACK call if this is the case.

https://github.com/quil-lang/quilc/pull/857

genos commented 1 year ago

Thanks so much, @Spin1Half! I'm kind of embarrassed that the fix was so simple but exceedingly grateful for it.