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
Desired output
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}
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:
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.
Related
I'm trying to investigate the behavior of the following Delayed Differential Equation using Python:
y''(t) = -y(t)/τ^2 - 2y'(t)/τ - Nd*f(y(t-T))/τ^2,
where f is a cut-off function which is essentially equal to the identity when the absolute value of its argument is between 1 and 10 and otherwise is equal to 0 (see figure 1), and Nd, τ and T are constants.
For this I'm using the package JiTCDDE. This provides a reasonable solution to the above equation. Nevertheless, when I try to add a noise on the right hand side of the equation, I obtain a solution which stabilize to a non-zero constant after a few oscillations. This is not a mathematical solution of the equation (the only possible constant solution being equal to zero). I don't understand why this problem arises and if it is possible to solve it.
I reproduce my code below. Here, for the sake of simplicity, I substituted the noise with an high-frequency cosine, which is introduced in the system of equation as the initial condition for a dummy variable (the cosine could have been introduced directly in the system, but for a general noise this doesn't seem possible). To simplify further the problem, I removed also the term involving the f function, as the problem arises also without it. Figure 2 shows the plot of the function given by the code.
from jitcdde import jitcdde, y, t
import numpy as np
from matplotlib import pyplot as plt
import math
from chspy import CubicHermiteSpline
# Definition of function f:
def functionf(x):
return x/4*(1+symengine.erf(x**2-Bmin**2))*(1-symengine.erf(x**2-Bmax**2))
#parameters:
τ = 42.9
T = 35.33
Nd = 8.32
# Definition of the initial conditions:
dt = .01 # Time step.
totT = 10000. # Total time.
Nmax = int(totT / dt) # Number of time steps.
Vt = np.linspace(0., totT, Nmax) # Vector of times.
# Definition of the "noise"
X = np.zeros(Nmax)
for i in range(Nmax):
X[i]=math.cos(Vt[i])
past=CubicHermiteSpline(n=3)
for time, datum in zip(Vt,X):
regular_past = [10.,0.]
past.append((
time-totT,
np.hstack((regular_past,datum)),
np.zeros(3)
))
noise= lambda t: y(2,t-totT)
# Integration of the DDE
g = [
y(1),
-y(0)/τ**2-2*y(1)/τ+0.008*noise(t)
]
g.append(0)
DDE = jitcdde(g)
DDE.add_past_points(past)
DDE.adjust_diff()
data = []
for time in np.arange(DDE.t, DDE.t+totT, 1):
data.append( DDE.integrate(time)[0] )
plt.plot(data)
plt.show()
Incidentally, I noticed that even without noise, the solution seems to be discontinuous at the point zero (y is set to be equal to zero for negative times), and I don't understand why.
As the comments unveiled, your problem eventually boiled down to this:
step_on_discontinuities assumes delays that are small with respect to the integration time and performs steps that are placed on those times where the delayed components points to the integration start (0 in your case). This way initial discontinuities are handled.
However, implementing an input with a delayed dummy variable introduces a large delay into the system, totT in your case.
The respective step for step_on_discontinuities would be at totT itself, i.e., after the desired integration time.
Thus when you reach for time in np.arange(DDE.t, DDE.t+totT, 1): in your code, DDE.t is totT.
Therefore you have made a big step before you actually start integrating and observing which may seem like a discontinuity and lead to weird results, in particular you do not see the effect of your input, because it has already “ended” at this point.
To avoid this, use adjust_diff or integrate_blindly instead of step_on_discontinuities.
These 2 variations of n choose r code got different answer although followed the correct definition
I saw that this code works,
import math
def nCr(n,r):
f = math.factorial
return f(n) // f(r) // f(n-r)
But mine did not:
import math
def nCr(n,r):
f = math.factorial
return int(f(n) / (f(r) * f(n-r)))
Use test case nCr(80,20) will show the difference in result. Please advise why are they different in Python 3, thank you!
No error message. The right answer should be 3535316142212174320, but mine got 3535316142212174336.
That's because int(a / b) isn't the same as a // b.
int(a / b) evaluates a / b first, which is floating-point division. And floating-point numbers are prone to inaccuracies, roundoff errors and the like, as .1 + .2 == 0.30000000000000004. So, at some point, your code attempts to divide really big numbers, which causes roundoff errors since floating-point numbers are of fixed size, and thus cannot be infinitely precise.
a // b is integer division, which is a different thing. Python's integers can be arbitrarily huge, and their division doesn't cause roundoff errors, so you get the correct result.
Speaking about floating-point numbers being of fixed size. Take a look at this:
>>> import math
>>> f = math.factorial
>>> f(20) * f(80-20)
20244146256600469630315959326642192021057078172611285900283370710785170642770591744000000000000000000
>>> f(80) / _
3.5353161422121743e+18
The number 3.5353161422121743e+18 is represented exactly as shown here: there is no information about the digits after the last 3 in 53...43 because there's nowhere to store it. But int(3.5353161422121743e+18) must put something there! Yet it doesn't have enough information. So it puts whatever it wants to so that float(int(3.5353161422121743e+18)) == 3.5353161422121743e+18.
I have two float variables, let's say they are phi = 1.34e8 and beta = -2.7e-6. How do I display both results in a plot label in latex scientific notation over two lines? I want the plot label to look like (in latex font):
\phi = 1.34 x 10^8
\beta = -2.7 x 10^-6
And what about I have other variables for error, e.g. phi_err = 7.1e7, and I want the legend to look like:
\phi = (1.34 +/- 0.71) x 10^8
Edit:
My current Matlab code:
txt1 = texlabel(['n2=',num2str(n2)]);
txt2 = texlabel(['beta=',num2str(beta)]);
figure(1)
plot(...)
text(0.7,0.8,{txt1,txt2},'Units','normalized')
And the plot text looks like the upper part of the attached figure. How do I display the text in scientific notation with the multiply sign and the base 10 instead of e? Also, if I want to add the error (let's say I set in Matlab beta=[-2.7e-6, 1.2e-6] where beta(1) is the value and beta(2) is the error), then show should I modify the above code so that the result looks like the lower part of the attached figure? For the example I give, how do I extract 2.7 and 1.2 before the e? And what if they are of different order of magnitude, e.g. the error is 1.2e-7, which means in the displayed text I have to change it from 1.2e-7 to 0.12e-6 and combine the error and the beta value.
Taking my first programming course in python. Instructions were to: Copy and paste your assembly language source code into your processor document. Using textmate as my processor document. Not sure how source code is supposed to look. This is what I have :
Objective: Calculate the area of a triangle
>>> base=4
>>> height=3
>>> area=1.0/2.0 * base* height
>>> print("Area is:", area)
Area is: 6.0
Is this accurate? I just copied and pasted what I got when I ran it in IDLE for Python
Your code is accurate - for the formula for a triangle, you should know is:
A = (1/2)*b *h
Therefore the math is correct, henceforth your code is correct. Now - a simpler way to do this is:
base, height = 4, 3
area=1/2 * base* height
print("Area is:", area)
With python, you can define 2 or more variables on one line, as long as both sides have equal parts.
For Example:
base, height, width = 4, 3, 2
Having it this way, saves space and is useful for when you want to have return statements in your functions.
def main(inp): # For this example we r going to use strings for simplicity sake.
return inp, inp + "1", inp + "2", inp + "3"
# We return 4 values on one line, where as we cannot use 4 lines of
# return because python will give us an Error
print(main("hello"))
Functions and Classes are part of OOP Programming Btw
See you next time you post,
Jerry
I have to use the math.exp() function to get the following value for x which is converted to scientific notation. However, when trying to compare to see if this number is greater than y, python thinks it is less than.
x = 4.0686596698143466e+186
y = 59425800000000000000000
if x >= y:
print:("x is greater than y")
I realize there are methods to turn very large numbers into smaller int but I feel that route is a little more complicated and above my learning curve than necessary. I just need a way to see if x > y and also curious why python doesn't support the comparison. Converting y to scientific notation using decimal only turns it into a string.
Disclaimer: still a beginner