Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A violent error via quil_to_native_quil on ARM64 #842

Closed
genos opened this issue Sep 1, 2022 · 15 comments · Fixed by #857
Closed

A violent error via quil_to_native_quil on ARM64 #842

genos opened this issue Sep 1, 2022 · 15 comments · Fixed by #857

Comments

@genos
Copy link

genos commented Sep 1, 2022

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
Copy link
Member

notmgsk commented Sep 1, 2022

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

@genos
Copy link
Author

genos commented Sep 1, 2022

@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
Copy link
Author

genos commented Sep 1, 2022

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
Copy link
Author

genos commented Sep 1, 2022

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
Copy link
Member

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
Copy link
Author

genos commented Sep 1, 2022

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
Copy link
Member

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
Copy link
Author

genos commented Sep 12, 2022

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
Copy link
Author

genos commented Sep 19, 2022

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
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
;;;; 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
# |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
Copy link
Contributor

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

@notmgsk
Copy link
Member

notmgsk commented Sep 20, 2022

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
Copy link
Author

genos commented Sep 20, 2022

@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
Copy link
Member

@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 added a commit to Spin1Half/quilc that referenced this issue Sep 30, 2022
It seems that LAPACK becomes unstable on ARM when attempting to
find the eigenvectors and eigenvalues of a diagonal matrix. This
instability is triggered in find-diagonalizer-in-e-basis. The
operation becomes trivial when run on a diagonal matrix, so we
check for this and return the identity to avoid making a
potentially unstable LAPACK call.

Fixes quil-lang#842.
@Spin1Half
Copy link
Contributor

@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.

#857

stylewarning pushed a commit that referenced this issue Sep 30, 2022
It seems that LAPACK becomes unstable on ARM when attempting to
find the eigenvectors and eigenvalues of a diagonal matrix. This
instability is triggered in find-diagonalizer-in-e-basis. The
operation becomes trivial when run on a diagonal matrix, so we
check for this and return the identity to avoid making a
potentially unstable LAPACK call.

Fixes #842.
@genos
Copy link
Author

genos commented Sep 30, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants