Search code examples
python-3.xlatexsympyfractions

Changing printing format for fractions using sympy and PythonTex


Below is a minimal working problem, of what I am working on. The file is a standard LaTeX file using sympy within pythontex, where I want to change how sympy displays fractions.

Concretely I would like to make the following changes, but have been struggling:

  • How can I make sympy display the full, and not inline version of it's fractions for some of its fractions? In particular I would like the last fraction 1/5 to instead be displayed in full. eg. \fraction{1}{5}
  • In the expression for the derivative, I have simplified the results, but I struggle to substitute the variable x with the fraction a/b. Whenever I substitute this expression into the fraction it fully simplifies the expression, which is not what I want. I just want to replace x with the fraction a/b (in this case 2/3 or 1/3 depending on the seed).

Below I have attached two images displaying what my code produces, and what I would like it to display. Do note that this is also stated in the two bullets above

Current output

enter image description here

Desired output

enter image description here

Code

\documentclass{article}
\usepackage{pythontex}
\usepackage{mathtools,amssymb}
\usepackage{amsmath}
\usepackage{enumitem}

\begin{document}

\begin{pycode}
import math
from sympy import *
from random import randint, seed

seed(2021)
\end{pycode}

\paragraph{Oppgave 3}

\begin{pycode}
a, b = randint(1,2), 3
ab = Rational(a,b)

pressure_num = lambda x: 1-x
pressure_denom = lambda x: 1+x

def pressure(x):
  return (1-x)/(1+x)

pressure_ab = Rational(pressure_num(ab),pressure_denom(ab))

x, y, z = symbols('x y z')
pressure_derivative = simplify(diff(pressure(x), x))
pressure_derivative_ab = pressure_derivative.xreplace({ x : Rational(a,b)}) 
\end{pycode}

The partial pressure of some reaction is given as
%
\begin{pycode}
print(r"\begin{align*}")
print(r"\rho(\zeta)")
print(r"=")
print(latex(pressure(Symbol('\zeta'))))
print(r"\qquad \text{for} \ 0 \leq \zeta \leq 1.")
print(r"\end{align*}")
\end{pycode}
%
\begin{enumerate}[label=\alph*)]
    \item Evaluate $\rho(\py{a}/\py{b})$. Give a physical interpretation of your
        answer.
    \begin{equation*}
        \rho(\py{a}/\py{b})
        = \frac{1-(\py{ab})}{1+\py{ab}}
        = \frac{\py{pressure_num(ab)}}{\py{pressure_denom(ab)}}
        \cdot \frac{\py{b}}{\py{b}}
        = \py{pressure_ab}
    \end{equation*}
\end{enumerate}

The derivative is given as
%
\begin{pycode}
print(r"\begin{align*}")
print(r"\rho'({})".format(ab))
print(r"=")
print(latex(pressure_derivative))
print(r"=")
print(latex(simplify(pressure_derivative_ab)))
print(r"\end{align*}")
\end{pycode}

\end{document}

Solution

  • Whenever I substitute this expression into the fraction it fully simplifies the expression, which is not what I want. I just want to replace x with the fraction a/b (in this case 2/3 or 1/3 depending on the seed).

    It's possible to do this, if we use a with expression to temporarily disable evaluation for that code block, and then we use two dummy variables in order to represent the fraction, and finally we do the substitution with numerical values.

    So the following line in your code:

    pressure_derivative_ab = pressure_derivative.xreplace({ x : Rational(a,b)}) 
    

    can be changed to:

    with evaluate(False):
        a1,b1=Dummy('a'),Dummy('b')
        pressure_derivative_ab = pressure_derivative.subs(x,a1/b1).subs({a1: a,b1: b})
    

    The expressions pressure_derivative and pressure_derivative_ab after this are:

    enter image description here

    How can I make sympy display the full, and not inline version of it's fractions for some of its fractions? In particular I would like the last fraction 1/5 to instead be displayed in full. eg. \fraction{1}{5}

    For this, you only need to change this line:

            = \py{pressure_ab}
    

    into this line:

            = \py{latex(pressure_ab)}
    

    Because we want pythontex to use the sympy latex printer, instead of the ascii printer.

    To summarize, the changes between the original code and the modified code can be viewed here.

    All the code in this post is also available in this repo.