********************** Sage, LaTeX 及其朋友们 ********************** Sage 与 TeX 的 LaTeX 方言之间存在着密切的协同关系。 本节旨在介绍各种交互方式,从最基本的开始,然后介绍一些不常见的用法。 基本使用 ======== Sage 中的每个“对象”都必须有 LaTeX 表示。你可以通过执行 ``latex(foo)`` 来获取这种表示, 其中 ``foo`` 是 Sage 中的某个对象。输出是一个字符串,当在 TeX 的数学模式中使用时 (例如,包围在一对单美元符号之间),该字符串应该能够准确地呈现 ``foo``。以下是一些示例。 :: sage: var('z') z sage: latex(z^12) z^{12} sage: latex(sqrt(z^2 + 1/2)) \sqrt{z^{2} + \frac{1}{2}} sage: latex('a string') \text{\texttt{a{ }string}} sage: latex(QQ) \Bold{Q} sage: latex(ZZ['x']) \Bold{Z}[x] sage: latex(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]])) \left(\begin{array}{rrr} 2 & 4 & 6 \\ -1 & -1 & -1 \end{array}\right) 通过这种方式,Sage 可以有效地用于构建 LaTeX 文档的各个部分: 在 Sage 中创建或计算一个对象 ``foo``,对该对象执行 ``latex(foo)``, 然后将 LaTeX 字符串剪切并粘贴到你的文档中。 命令 ``view(foo)`` 会显示对象 ``foo`` 的渲染后的 LaTeX 表示。 在后台,该命令会运行 ``latex(foo)`` 并将 LaTeX 字符串合并到一个简单的 LaTeX 文档中, 用系统范围内的 TeX 安装处理该文档,然后调用合适的查看器来显示输出。 在 Jupyter Notebook 中,你可以自动看到输入命令输出的渲染 LaTeX 表示。 你可以通过执行 ``%display latex`` 来启动自动渲染(并通过执行 ``%display plain`` 停止)。 .. ONLY:: html 因此,在 Jupyter notebook 中,你得到 .. JUPYTER-EXECUTE:: %display latex var('z') z^12 .. JUPYTER-EXECUTE:: sqrt(z^2 + 1/2) .. JUPYTER-EXECUTE:: 'a string' .. JUPYTER-EXECUTE:: QQ .. JUPYTER-EXECUTE:: ZZ['x'] .. JUPYTER-EXECUTE:: matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]]) .. JUPYTER-EXECUTE:: %display plain Jupyter Notebook 使用 `MathJax <http://www.mathjax.org>`_ 在网页浏览器中清晰地渲染数学内容。 MathJax 是一个开源的 JavaScript 数学显示引擎,可以在所有现代浏览器中使用。 它能够渲染大部分 LaTex,但并不支持完整的 LaTeX,是 LaTex 的子集。 它不支持复杂表格、分段或文档管理,因为它主要用于准确渲染 LaTeX 数学片段。 在 Jupyter Notebook 中自动 LaTeX 渲染(启用 ``%display latex``) 是通过 :class:`sage.misc.html.MathJax` 类内部实现的。 该类的对象将 Sage 对象通过 ``latex()`` 转换为 MathJax 需要的 HTML 形式,然后将其包装在 HTML 中。 :: sage: from sage.misc.html import MathJax sage: mj = MathJax() sage: var('z') z sage: mj(z^12) <html>\[z^{12}\]</html> sage: mj(sqrt(z^2 + 1/2)) <html>\[\sqrt{z^{2} + \frac{1}{2}}\]</html> sage: mj('a string') <html>\[\verb|a|\verb| |\verb|string|\]</html> sage: mj(QQ) <html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html> sage: mj(ZZ['x']) <html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Z}[x]\]</html> sage: mj(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]])) <html>\[\left(\begin{array}{rrr} 2 & 4 & 6 \\ -1 & -1 & -1 \end{array}\right)\]</html> 如果你需要了解 Sage 对象的 LaTeX 渲染,那么了解这一点很有用。 .. _sec-custom-generation: 自定义 LaTeX 生成 ================= 有几种方法可以自定义由 ``latex()`` 命令生成的实际 LaTeX 代码。 预定义对象 ``latex`` 包含多个方法,可以通过输入 ``latex.`` (注意这里有一个点)后按 :kbd:`Tab` 键来列出这些方法。 ``latex.matrix_delimiters`` 方法是一个很好的例子。 它可以用来更改矩阵周围的符号 -- 大括号、方括号、花括号、竖线。 不强制执行任何样式,你可以随意混合搭配。 注意,LaTeX 所需的反斜杠在 Python 字符串中需要额外加一个斜杠以便正确转义。 :: sage: A = matrix(ZZ, 2, 2, range(4)) sage: latex(A) \left(\begin{array}{rr} 0 & 1 \\ 2 & 3 \end{array}\right) sage: latex.matrix_delimiters(left='[', right=']') sage: latex(A) \left[\begin{array}{rr} 0 & 1 \\ 2 & 3 \end{array}\right] sage: latex.matrix_delimiters(left='\\{', right='\\}') sage: latex(A) \left\{\begin{array}{rr} 0 & 1 \\ 2 & 3 \end{array}\right\} ``latex.vector_delimiters`` 方法的工作原理与之类似。 常见环和域(整数、有理数、实数等)的排版方式可以通过 ``latex.blackboard_bold`` 方法来控制。 这些集合默认以粗体排版,但有时可以选择以双重划线格式书写,如某些书面作品所做的那样。 这可以通过重新定义 Sage 内置的 ``\Bold{}`` 宏来实现。 :: sage: latex(QQ) \Bold{Q} sage: from sage.misc.html import MathJax sage: mj = MathJax() sage: mj(QQ) <html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html> sage: latex.blackboard_bold(True) sage: mj(QQ) <html>\[\newcommand{\Bold}[1]{\mathbb{#1}}\Bold{Q}\]</html> sage: latex.blackboard_bold(False) .. ONLY:: html 在 Jupyter notebook 中, .. JUPYTER-EXECUTE:: %display latex QQ .. JUPYTER-EXECUTE:: latex.blackboard_bold(True) QQ .. JUPYTER-EXECUTE:: latex.blackboard_bold(False) %display plain 可以通过加入新的宏来利用 LaTeX 的可扩展性。可以添加单个宏,以便在 MathJax 解释 LaTeX 片段时使用。 :: sage: latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}") sage: latex.extra_macros() '\\newcommand{\\sqrt}[1]{(#1)^\\frac{1}{2}}' sage: var('x y') (x, y) sage: latex(sqrt(x+y)) \sqrt{x + y} sage: from sage.misc.html import MathJax sage: mj = MathJax() sage: mj(sqrt(x + y)) <html>\[\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}\sqrt{x + y}\]</html> sage: latex.extra_macros('') .. ONLY:: html 在 Jupyter notebook 中, .. JUPYTER-EXECUTE:: %display latex var('x y') sqrt(x + y) .. JUPYTER-EXECUTE:: latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}") sqrt(x + y) .. JUPYTER-EXECUTE:: latex.extra_macros('') %display plain .. _sec-custom-processing: 自定义 LaTeX 处理 ================= 系统范围内的 TeX 被调用来处理完整的 LaTeX 文档,例如,当你 ``view(foo)`` 时, 其中 ``foo`` 是一个复杂的 Sage 对象,太复杂以至于 ``MathJax`` 无法处理。 命令 ``latex_extra_preamble`` 用于构建完整 LaTeX 文档的导言部分,下面将展示如何完成这项工作。 如往常一样,请注意 Python 字符串中需要双反斜杠。 :: sage: latex.extra_macros('') sage: latex.extra_preamble('') sage: from sage.misc.latex import latex_extra_preamble sage: print(latex_extra_preamble()) \newcommand{\ZZ}{\Bold{Z}} ... \newcommand{\Bold}[1]{\mathbf{#1}} sage: latex.add_macro("\\newcommand{\\foo}{bar}") sage: print(latex_extra_preamble()) \newcommand{\ZZ}{\Bold{Z}} ... \newcommand{\Bold}[1]{\mathbf{#1}} \newcommand{\foo}{bar} 同样,对于更大或更复杂的 LaTeX 表达式,可以将包(或其他任意内容)添加到 LaTeX 文件的导言部分。 任意内容都可以通过 ``latex.add_to_preamble`` 命令加入导言部分, 专用命令 ``latex.add_package_to_preamble_if_available`` 会首先检查某个包是否实际存在, 然后尝试将其添加到导言部分。 这里我们将几何包添加到导言部分并用它来设置 TeX 将在页面上使用的区域尺寸(有效地设置边距)。 如往常一样,请注意 Python 字符串中需要双反斜杠。 :: sage: from sage.misc.latex import latex_extra_preamble sage: latex.extra_macros('') sage: latex.extra_preamble('') sage: latex.add_to_preamble('\\usepackage{geometry}') sage: latex.add_to_preamble('\\geometry{letterpaper,total={8in,10in}}') sage: latex.extra_preamble() '\\usepackage{geometry}\\geometry{letterpaper,total={8in,10in}}' sage: print(latex_extra_preamble()) \usepackage{geometry}\geometry{letterpaper,total={8in,10in}} \newcommand{\ZZ}{\Bold{Z}} ... \newcommand{\Bold}[1]{\mathbf{#1}} 可以通过检查其存在性来添加特定包,以下示例展示了这种情况。作为示例,我们将尝试向导言部分添加一个可能不存在的包。 :: sage: latex.extra_preamble('') sage: latex.extra_preamble() '' sage: latex.add_to_preamble('\\usepackage{foo-bar-unchecked}') sage: latex.extra_preamble() '\\usepackage{foo-bar-unchecked}' sage: latex.add_package_to_preamble_if_available('foo-bar-checked') sage: latex.extra_preamble() '\\usepackage{foo-bar-unchecked}' 使用哪种 TeX 方言,以及输出和相关查看器的性质,也可以定制。 .. NOTE:: Sage 几乎包括了构建和使用 Sage 所需的一切,但一个重要的例外是 TeX 本身。 因此,在以下情况下,你需要安装完整的 TeX 系统以及一些相关的转换工具。 许多版本的 Linux 都有基于 TeXLive 的软件包,macOS 有 MacTeX,Windows 有 MiKTeX。 可以使用 ``latex.engine()`` 命令控制是否使用系统范围内的 ``latex``, ``pdflatex`` 或 ``xelatex`` 可执行文件。 当调用 ``view()`` 并且引擎设置为 ``latex`` 时,会生成一个 dvi 文件,Sage 会使用 dvi 查看器(如 xdvi)来显示结果。 相比之下,当引擎设置为 ``pdflatex`` 时,调用 ``view()`` 会生成 PDF 文件, 并且 Sage 会调用系统的 PDF 文件查看工具(如 acrobat, okular, evince 等)。 对于使用这些工具的练习,有一些预先打包好的示例。 要使用这些示例,需要导入 ``sage.misc.latex.latex_examples`` 对象, 这是 :class:`sage.misc.latex.LatexExamples` 类的一个实例,如下所示。 目前该类有交换图、组合图、扭结理论和 pstricks 的示例,分别使用以下包:xy,tkz-graph,xypic,pstricks。 导入后,对 ``latex_examples`` 使用 tab 补全查看内置示例。 调用每个示例会返回一些关于如何正确呈现该示例的说明。要实际查看示例,需要使用 ``view(foo)`` (导言部分、引擎等均设置正确)。 :: sage: from sage.misc.latex import latex_examples sage: foo = latex_examples.diagram() sage: foo LaTeX example for testing display of a commutative diagram produced by xypic. <BLANKLINE> To use, try to view this object -- it will not work. Now try 'latex.add_to_preamble("\\usepackage[matrix,arrow,curve,cmtip]{xy}")', and try viewing again. You should get a picture (a part of the diagram arising from a filtered chain complex). 为了展示如何处理复杂的 LaTeX 表达式,让我们看一下使用 ``tkz-graph`` LaTeX 包的组合图示例。 .. NOTE:: ``tkz-graph`` LaTeX 包建立在 ``pgf`` 库的 ``tikz`` 前端之上。 渲染组合图需要 ``pgf`` 库以及文件 ``tkz-graph.sty`` 和 ``tkz-berge.sty``。 它们很可能已经是系统范围内 TeX 安装的一部分。即使不是,也应当很容易找到安装指南。 首先,我们通过将相关包添加到 LaTeX 文档的导言部分来确保它们被包含在内。 :: sage: latex.extra_preamble('\\usepackage{tikz}\n\\usepackage{tkz-graph}\n' ....: '\\usepackage{tkz-berge}\n\\usetikzlibrary{arrows,shapes}') 当使用 dvi 文件作为中间格式时,图形无法正确生成,因此最好将 LaTeX 引擎设置为 ``pdflatex`` 可执行文件。 :: sage: latex.engine('pdflatex') 此时,像 ``view(graphs.CompleteGraph(4))`` 这样的命令应该生成一个带有完整图 `K_4` 适当图像的 PDF。 实际上,可以省略前面的步骤,因为导言部分会自动正确设置,并且 ``pdflatex`` 是 Sage 的默认 LaTeX 引擎。 重新启动 Sage 后再次尝试该命令。 注意,通过 ``tkz-graph`` 有多种选项可以影响 LaTeX 中图形的呈现方式,这超出了本节的范围。 请参阅参考手册 :ref:`sage.graphs.graph_latex` 章节获取指令和详细信息。 SageTeX ======= SageTeX 是一个可以进一步集成 TeX 和 Sage 的程序。 它是一组 TeX 宏,允许 LaTeX 文档包含指令,让 Sage 计算各种对象并使用 ``latex()`` 格式化对象。 更多信息请参见 :ref:`sec-sagetex`。