# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
Tools to create LaTeX arrays.
"""
import numpy as np
from qiskit.exceptions import MissingOptionalLibraryError
def _num_to_latex(raw_value, decimals=15, first_term=True, coefficient=False):
"""Convert a complex number to latex code suitable for a ket expression
Args:
raw_value (complex): Value to convert.
decimals (int): Number of decimal places to round to (default 15).
coefficient (bool): Whether the number is to be used as a coefficient
of a ket.
first_term (bool): If a coefficient, whether this number is the first
coefficient in the expression.
Returns:
str: latex code
"""
import sympy # runtime import
raw_value = np.around(raw_value, decimals=decimals)
value = sympy.nsimplify(raw_value, rational=False)
if isinstance(value, sympy.core.numbers.Rational) and value.denominator > 50:
# Avoid showing ugly fractions (e.g. 50498971964399/62500000000000)
value = value.evalf() # Display as float
if isinstance(value, sympy.core.numbers.Float):
value = round(value, decimals)
element = sympy.latex(value, full_prec=False)
if not coefficient:
return element
if isinstance(value, sympy.core.Add):
# element has two terms
element = f"({element})"
if element == "1":
element = ""
if element == "-1":
element = "-"
if not first_term and not element.startswith("-"):
element = f"+{element}"
return element
def _matrix_to_latex(matrix, decimals=10, prefix="", max_size=(8, 8)):
"""Latex representation of a complex numpy array (with maximum dimension 2)
Args:
matrix (ndarray): The matrix to be converted to latex, must have dimension 2.
decimals (int): For numbers not close to integers, the number of decimal places
to round to.
prefix (str): Latex string to be prepended to the latex, intended for labels.
max_size (list(```int```)): Indexable containing two integers: Maximum width and maximum
height of output Latex matrix (including dots characters). If the
width and/or height of matrix exceeds the maximum, the centre values
will be replaced with dots. Maximum width or height must be greater
than 3.
Returns:
str: Latex representation of the matrix
Raises:
ValueError: If minimum value in max_size < 3
"""
if min(max_size) < 3:
raise ValueError("""Smallest value in max_size must be greater than or equal to 3""")
out_string = f"\n{prefix}\n"
out_string += "\\begin{bmatrix}\n"
def _elements_to_latex(elements):
# Takes a list of elements (a row) and creates a latex
# string from it; Each element separated by `&`
el_string = ""
for el in elements:
num_string = _num_to_latex(el, decimals=decimals)
el_string += num_string + " & "
el_string = el_string[:-2] # remove trailing ampersands
return el_string
def _rows_to_latex(rows, max_width):
# Takes a list of lists (list of 'rows') and creates a
# latex string from it
row_string = ""
for r in rows:
if len(r) <= max_width:
row_string += _elements_to_latex(r)
else:
row_string += _elements_to_latex(r[: max_width // 2])
row_string += "& \\cdots & "
row_string += _elements_to_latex(r[-max_width // 2 + 1 :])
row_string += " \\\\\n "
return row_string
max_width, max_height = max_size
if matrix.ndim == 1:
out_string += _rows_to_latex([matrix], max_width)
elif len(matrix) > max_height:
# We need to truncate vertically, so we process the rows at the beginning
# and end, and add a line of vertical elipse (dots) characters between them
out_string += _rows_to_latex(matrix[: max_height // 2], max_width)
if max_width >= matrix.shape[1]:
out_string += "\\vdots & " * matrix.shape[1]
else:
# In this case we need to add the diagonal dots in line with the column
# of horizontal dots
pre_vdots = max_width // 2
post_vdots = max_width // 2 + np.mod(max_width, 2) - 1
out_string += "\\vdots & " * pre_vdots
out_string += "\\ddots & "
out_string += "\\vdots & " * post_vdots
out_string = out_string[:-2] + "\\\\\n "
out_string += _rows_to_latex(matrix[-max_height // 2 + 1 :], max_width)
else:
out_string += _rows_to_latex(matrix, max_width)
out_string += "\\end{bmatrix}\n"
return out_string
[documentos]def array_to_latex(array, precision=10, prefix="", source=False, max_size=8):
"""Latex representation of a complex numpy array (with dimension 1 or 2)
Args:
array (ndarray): The array to be converted to latex, must have dimension 1 or 2 and
contain only numerical data.
precision (int): For numbers not close to integers or common terms, the number of
decimal places to round to.
prefix (str): Latex string to be prepended to the latex, intended for labels.
source (bool): If ``False``, will return IPython.display.Latex object. If display is
``True``, will instead return the LaTeX source string.
max_size (list(int) or int): The maximum size of the output Latex array.
* If list(``int``), then the 0th element of the list specifies the maximum
width (including dots characters) and the 1st specifies the maximum height
(also inc. dots characters).
* If a single ``int`` then this value sets the maximum width _and_ maximum
height.
Returns:
str or IPython.display.Latex: If ``source`` is ``True``, a ``str`` of the LaTeX
representation of the array, else an ``IPython.display.Latex`` representation of
the array.
Raises:
TypeError: If array can not be interpreted as a numerical numpy array.
ValueError: If the dimension of array is not 1 or 2.
MissingOptionalLibraryError: If ``source`` is ``False`` and ``IPython.display.Latex`` cannot be
imported.
"""
try:
array = np.asarray(array)
_ = array[0] + 1 # Test first element contains numerical data
except TypeError as err:
raise TypeError(
"""array_to_latex can only convert numpy arrays containing numerical data,
or types that can be converted to such arrays"""
) from err
if array.ndim > 2:
raise ValueError("array_to_latex can only convert numpy ndarrays of dimension 1 or 2")
if isinstance(max_size, int):
max_size = (max_size, max_size)
outstr = _matrix_to_latex(array, decimals=precision, prefix=prefix, max_size=max_size)
if source is True:
return outstr
try:
from IPython.display import Latex
except ImportError as err:
raise MissingOptionalLibraryError(
libname="IPython",
name="array_to_latex",
pip_install="pip install ipython",
) from err
return Latex(f"$${outstr}$$")