Python 3.x finding derivatives - python-3.x

I'm trying to make a derivative calculator.
Here is my code.
from sympy import symbols, Limit, S
x, h = symbols('x, h')
def g(x):
def f(x):
y = input("Function:")
return eval(y, {'__builtins__': {}}, {'x': x})
return Limit((f(x+h)-f(x))/h , h, S.Zero).doit()
print (g(x))
But when I run the code, I have to put the "Functions" twice. It seems that it happens because there are two f's ( f(x+h) and f(x) ) when g(x) is defined.
How can I fix it? I mean, I don't want to put my function two times...
Anyone can help me?

Related

oneliner using reduce in python

I'm trying to take my Python skills (beginner) to the next level.
and I'm trying to teach myself the functools.reduce() function
So I'm running every time into the same error;
I'd appreciate if someone could explain to me what is the problem in my code
I'm trying to build a simple func that receive a number and return the sum of number digits
import functools
def sum_using_reduce(number):
return str(number)[0] + str(number)[1]
number = 104
print(functools.reduce(sum_using_reduce, number))
Try this:
number = 104
functools.reduce(lambda x, y: x+y, [int(i) for i in str(number)])
Output: 5
Using your example:
import functools
def sum_using_reduce(x, y) -> int:
return x + y
print(functools.reduce(sum_using_reduce, [int(i) for i in str(105)]))
Output: 6
Another approach:
import functools
def sum_using_reduce(number: int) -> int:
return functools.reduce(lambda x, y: x+y, [int(i) for i in str(number)])
print(sum_using_reduce(124))
Output: 7
In your sum_using_reduce function you are trying to sum two strings, which would simply perform concatenation. Moreover, you are providing an integer as the second argument to the reduce function, where the reduce function requires an iterable to be provided.
Below is a solution that fixes both these requirements:
from functools import reduce
number=104
print(reduce(lambda x,y:x+y,map(int,str(number))))
map(int,str(number)) transforms the number to a string (104->"104") and then turns every character in the string to an integer, returning an iterable map object ("104"->[1,0,4]).
lambda x,y:x+y is a function which takes two integers and sums them.

define a "derivation" function in sympy

I am trying to make a derivation Function in sympy (I am using sympy version 1.4), but I am not sure how. In particular, I am trying to define a general function (that could just take sympy variables, not functions for now) that has the following properties:
d(f+g)=d(f)+d(g)
d(f*g)=f*d(g)+d(f)*g
I have tried reading the sympy documentation on defining Functions but I am not sure how to define a Function class that has the above properties for any two symbols.
For some background/context, I know how to make derivations in Mathematica; I would just type
d[f_+g_]:=d[f]+d[g]
d[f_ g_]:=f d[g] + d[f] g
You can write your own rule. The following might get you started:
def d(e, func):
"""
>>> from sympy import x, y
>>> from sympy import Function
>>> D = Function('D')
>>> d(x + y, D)
D(x) + D(y)
"""
if e.is_Add:
return Add(*[d(a, func) for a in e.args])
elif e.is_Mul:
return Add(*[Mul(*(e.args[:i]+(d(e.args[i],func),)+e.args[i+1:]))
for i in range(len(e.args))])
else:
return func(e)
Or you could try this with a class:
class d(Function):
#classmethod
def eval(cls, e):
if e.is_Add:
return Add(*[d(a) for a in e.args])
elif e.is_Mul:
return Add(*[Mul(*(e.args[:i]+(d(e.args[i]),)+e.args[i+1:]))
for i in range(len(e.args))])
else:
return d(e, evaluate=False)
See also, linapp.

Numpy: division by zero error, but mathematically function is apparently defined

I'm testing out some functions to fit with data, and one of them (in 2-D) is
f(x) = (1/(1-x)) / (1 + 1/(1-x))
Which, according to Wolfram and the Google plotters, gives you the result
f(1) = 1
I've tried to get this to work without hard coding the case
if x == 1:
return 1
but I end up with a nan and a RunTimeWarning informing me that I have indeed divided by zero.
import numpy as np
def f(x):
return 1/(1-x) / (1 + 1/(1-x))
x_range = np.linspace(0, 1, 50)
y = f(x_range)
print(y)
Is there a more elegant solution than to simply introduce a hard-coded if?
Is there a reason to keep it in this form, you can simplify it to:
def f(x):
return 1/(2-x)
Wolfram and Google probably to some sort of algebraic simplification too.
Just simplify the equation for f(x) = (1/(1-x)) / (1 + 1/(1-x)). The simplified equation will be (1/(2-x)). Now update the program as:
import numpy as np
def f(x):
return 1/(2-x)
x_range = np.linspace(0, 1, 50)
y = f(x_range)
print(y)
output:
[0.5 0.50515464 0.51041667 0.51578947 0.5212766 0.52688172
0.5326087 0.53846154 0.54444444 0.5505618 0.55681818 0.56321839
0.56976744 0.57647059 0.58333333 0.59036145 0.59756098 0.60493827
0.6125 0.62025316 0.62820513 0.63636364 0.64473684 0.65333333
0.66216216 0.67123288 0.68055556 0.69014085 0.7 0.71014493
0.72058824 0.73134328 0.74242424 0.75384615 0.765625 0.77777778
0.79032258 0.80327869 0.81666667 0.83050847 0.84482759 0.85964912
0.875 0.89090909 0.90740741 0.9245283 0.94230769 0.96078431
0.98 1. ]

Python, scipy - How to fit a curve using a piecewise function with a conditional parameter that also needs to be calculated?

As the title suggests, I'm trying to fit a piecewise equation to a large data set. The equations I would like to fit to my data are as follows:
y(x) = b, when x < c
else:
y(x) = b + exp(a(x-c)) - 1, when x >= c
There are multiple answers to how such an issue can be addressed, but as a Python beginner I can't figure out how to apply them to my problem:
Curve fit with a piecewise function?
Conditional curve fit with scipy?
The problem is that all variables (a,b and c) have to be calculated by the fitting algorithm.
Thank you for your help!
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
# Reduced Dataset
y = np.array([23.032, 21.765, 20.525, 21.856, 21.592, 20.754, 20.345, 20.534,
23.502, 21.725, 20.126, 21.381, 20.217, 21.553, 21.176, 20.976,
20.723, 20.401, 22.898, 22.02 , 21.09 , 22.543, 22.584, 22.799,
20.623, 20.529, 20.921, 22.505, 22.793, 20.845, 20.584, 22.026,
20.621, 23.316, 22.748, 20.253, 21.218, 23.422, 23.79 , 21.371,
24.318, 22.484, 24.775, 23.773, 25.623, 23.204, 25.729, 26.861,
27.268, 27.436, 29.471, 31.836, 34.034, 34.057, 35.674, 41.512,
48.249])
x = np.array([3756., 3759., 3762., 3765., 3768., 3771., 3774., 3777., 3780.,
3783., 3786., 3789., 3792., 3795., 3798., 3801., 3804., 3807.,
3810., 3813., 3816., 3819., 3822., 3825., 3828., 3831., 3834.,
3837., 3840., 3843., 3846., 3849., 3852., 3855., 3858., 3861.,
3864., 3867., 3870., 3873., 3876., 3879., 3882., 3885., 3888.,
3891., 3894., 3897., 3900., 3903., 3906., 3909., 3912., 3915.,
3918., 3921., 3924.])
# Simple exponential function without conditions (works so far)
def exponential_fit(x,a,b,c):
return b + np.exp(a*(x-c))
popt, pcov = curve_fit(exponential_fit, x, y, p0 = [0.1, 20,3800])
plt.plot(x, y, 'bo')
plt.plot(x, exponential_fit(x, *popt), 'r-')
plt.show()
You should change your function to something like
def exponential_fit(x, a, b, c):
if x >= c:
return b + np.exp(a*(x-c))-1
else:
return b
Edit: As chaosink pointed out in the comments, this approach no longer works as the the above function assumes that x is a scalar. However, curve_fit evaluates the function for array-like x. Consequently, one should use vectorised operations instead, see here for more details. To do so, one can either use
def exponential_fit(x, a, b, c):
return np.where(x >= c, b + np.exp(a*(x-c))-1, b)
or chaosink's suggestion in the comments:
def exponential_fit(x, a, b, c):
mask = (x >= c)
return mask * (b + np.exp(a*(x-c)) - 1) + ~mask * b
Both give:

Trapezoidal approximation error plotting in python

Im trying to code a function that plots the error of the composite trapezoidal rule against the step size.
Obviously this doesn't look to good since i'm just starting to learn these things.
Anyhow i managed to get the plot and everything, but i'm supposed to get a plot with slope 2, so i am in need of help to figure out where i did go wrong.
from scipy import *
from pylab import *
from matplotlib import *
def f(x): #define function to integrate
return exp(x)
a=int(input("Integrate from? ")) #input for a
b=int(input("to? ")) #inpput for b
n=1
def ctrapezoidal(f,a,b,n): #define the function ctrapezoidal
h=(b-a)/n #assign h
s=0 #clear sum1-value
for i in range(n): #create the sum of the function
s+=f(a+((i)/n)*(b-a)) #iterate th sum
I=(h/2)*(f(a)+f(b))+h*s #the function + the sum
return (I, h) #returns the approximation of the integral
val=[] #start list
stepsize=[]
error=[]
while len(val)<=2 or abs(val[-1]-val[-2])>1e-2:
I, h=ctrapezoidal(f,a,b,n)
val.append(I)
stepsize.append(h)
n+=1
for i in range(len(val)):
error.append(abs(val[i]-(e**b-e**a)))
error=np.array(error)
stepsize=np.array(stepsize)
plt.loglog(stepsize, error, basex=10, basey=10)
plt.grid(True,which="both",ls="steps")
plt.ylabel('error')
plt.xlabel('h')

Resources