Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
5.16k stars 2.35k forks source link

Improve latex implementation on matplotlib and add font customization. #11346

Open alex180500 opened 10 months ago

alex180500 commented 10 months ago

What should we add?

It would be nice to add font customization other than size in matplotlib. Like font family (serif would be much appreciated) and also the font itself.

When trying to add:

import matploltib
matplotlib.rc("font", family="serif")

Some of the text is now rendered correctly while most is just fixed as serif. I think there is something messy going on with the latex implementation and sometimes it renders sometimes it's not. For example, why is there all that jargain on MatplotlibDrawer._get_text_width() with LatexNodes2Text? Matplotlib nowadays renders latex perfectly one just need the math text to be enclosed with $.

Another good example is QuantumCircuit.if_test. This is an example:

from qiskit import QuantumCircuit

qc = QuantumCircuit(2, 2)

qc.h(0)
qc.measure(0, 0)
with qc.if_test((0, 1)):
    qc.x(0)
qc.measure(0, 1)

qc.draw(style="clifford")

This is the output: output

As you can see, the classical register condition is not rendered correctly in latex.

enavarro51 commented 10 months ago

@alex180500 A little history. Three years ago we added the text width calculation to the mpl drawer so that gate/instruction boxes would grow to fit the length of the longest text in the box. In researching this, it seems the only way to do this precisely is using the get_renderer method and rendering the text and then calling get_window_extent to get the width. There are several discussions of this on stackoverflow, this being one, https://stackoverflow.com/questions/22667224/get-text-bounding-box-independent-of-backend.

The fundamental problem is that not all matplotlib backends support get_renderer including the one that was then in use for qiskit CI tests, ps. So the hacky solution was to use a known backend with get_renderer to create the _char_list table that is in use in the mpl drawer. Somewhat amazingly this still appears to work across multiple backends. It was done using the standard sans serif type, so use of other fonts was not considered.

If someone wants to investigate the current state of get_renderer, it might be possible to bring it into use, which would allow the removal of the _char_list table and would allow for the code to be modified to use other fonts. Since we are moving into larger circuits, it would also have to be shown that there is no significant performance degradation if get_renderer is used.

In regard to your second issue about the register display, I believe this was a conscious choice at the time. The image you show at the top has large gates, but in a more typical rendering with maybe 10 qubits and a few hundred gates, the subfont size that displays on a typical device is just at the edge of readability. If you show the c_0 with the 0 as a subscript, it can become unreadable in the font we are using. Again something that could be revisited.