I'm trying to create a function that will do a least squares fit based on a passed in lambda function. I want to create an array of zeroes of length equal to that of the number of arguments taken by the lambda function for the initial guess to the lambda function. so if its linear I want [0,0] and for quadratic I want [0,0,0].
#polynomial functions
linear = lambda p, x: p[0] * x + p[1]
quadratic = lambda p, x: p[0] * x**2 + p[1] * x + p[2]
cubic = lambda p, x: p[0] * x**3 + p[1] * x**2 + p[2] * x + p[3]
#polynomial functions forced through 0
linear_zero = lambda p, x: p[0] * x
quadratic_zero = lambda p, x: p[0] * x**2 + p[1] * x
cubic_zero = lambda p, x: p[0] * x**3 + p[1] * x**2 + p[2] * x
def linFit(x, y,fitfunc):
errfunc = lambda p, x, y: fitfunc(p, x) - y
Here I want to create a array of zeros. But at this point p isn't defined. so len(p) does not work.
init_p = np.array(zeros(len(p))) #bundle initial values in initial parameters
p1, success = optimize.leastsq(errfunc, init_p.copy(), args = (x, y))
return p1
under python >= 2.7:
>>> l = lambda a, b: None
>>> l.func_code.co_argcount
2
or under 2.6:
>>> l.__code__.co_argcount
2
by looking at it's code object __code__:
>>> p=lambda x,y:x+y
>>> len(p.__code__.co_varnames)
2
>>> p.__code__.co_varnames
('x', 'y')
Related
I have a two functions where I set parameters for mathematical function. I would like to create one if possible where I would type:
x, y = one_demo_fun(a=1,
b=2,
c=5,
power_of_the_first_x=2,
power_of_the_second_x=1))
or
x, y = one_demo_fun(y = 1 * (x ** 2) + (2 * x) + 5)
and get the same result.
I have two functions which I would like to make one, where user can type one of above:
def function_demo_parameters( # type function settings ax^2+bx+c
a=1,
b=1,
c=1,
power_of_the_first_x=2,
power_of_the_second_x=1):
x = np.linspace(-2, 2, 100)
y = a * (x ** power_of_the_first_x) + b * (x ** power_of_the_second_x) + c
return x, y
def function_demo_equation( # type function
y=1 * (x ** 2) + (2 * x) + 5):
x = np.linspace(-2, 2, 100)
y = y
return x, y
x, y = function_demo_parameters()
x_1, y_1 = function_demo_equation()
Is there some way to merge them or other way to look at the problem?
You don't want an equation; you want the function that the equation implies.
function_demo_equation(lambda x: 1*(x**2) + 2*x + 5)
I wrote this program describing an algorithm for the simulation of a partial differential equation. The basic functions I use are defined by
import numpy as np
import math
from scipy import integrate, stats
def shift(func, x, a=0):
return func(x-a)
def scale(func, a=1):
return a*func
def trunc(func, x):
if x <= 0:
return 0
else:
return func(x)
def quad(func, a, b):
return integrate.quad(func, a, b)
def gauss(func, t, x):
def pregau(z):
k = (-t ** (1 / 2)) * z
return shift(func, x, k)*math.exp(-(z**2)/2)
fa = (1 / ((2 * math.pi) ** (1 / 2)) * integrate.quad(pregau, -np.inf, np.inf)[0])
return fa
The program then simulates the solution to the partial differential equation by
def vundl(x, u, l0=0.0, a=a, b=b, c=c):
v = [u(x)]
l = [l0]
f_temp_rec = u
for i in range(10):
def f_temp(x):
y = x - c * dt + B[i + 1] * 2 * a
z = b * dt
return gauss(f_temp_rec, z, y)
li = l[i] + quad(f_temp, 0, np.inf)[0]
l = np.append(l, li)
if x <= 0:
v = np.append(v, 0)
f_temp_rec = 0
else:
f_temp_rec = f_temp
v = np.append(v, f_temp(x))
return [v, l]
def u0(x):
return stats.beta.pdf(x, 2.7, 3.05)
print(vundl(x = 0.5, u0))
If I run this program for N=0 it produces a vector. Running the program for N>0 gives me the following error:
"RecursionError: maximum recursion depth exceeded"
but it actually should give me a vector v and a vector l.
I'm not sure exactly what you're trying to do in vundl with f_temp and f_temp_rec, but in the else: block you assign:
f_temp_rec = f_temp
and then call f_temp which calls gauss(f_temp_rec, z, y). Since at this point f_temp_rec is f_temp the function f_temp calls itself in an infinite recursion.
You should be able to see in in traceback that f_temp is calling itself repeatedly.
I'm having a problem finding out how to discover the write function to solve this problem:
Write a function that will take as an input two numbers (l,m) and return as a tuple the coefficients (a,b,c) for the quadratic equation a x^2 + b x + c found from expanding (x + l) * (x + m).
def func(l,m):
a = 1
equation = (a * (x ** 2)) + (b * x) + c
coef = [a,b,c]
eq2 = (x + m) * (x + l)
coef1 = m + l
coef2 = m * l
if coef1 == coef[1] and coef2 == coef[2]:
return coef
func(2,2)
Just to make it clear:
Your problem states:
return as a tuple the coefficients (a,b,c) for the quadratic equation
a x^2 + b x + c found from expanding (x + l) * (x + m).
Let's find the equation by expanding:
(x + l) * (x + m) =
= x^2 + l*x + m*x + l*m =
= x^2 + (l+m)*x + l*m
Now, by coefficients comparison with a x^2 + b x + c, we get that:
a = 1
b = l + m
c = l * m
So your function can basically return (1, l + m, l * m) directly...
Now that we have your code, I can tell you you're not using Python functions right. You can't create an unknown variable as you can do in math (here you called x)
There are modules who allow such operation with different syntax such as SymPy.
If you don't want to use it and you want to solve it "by-hand" maybe for a school project you'll need to compute a, b and conly from l and m with formulas.
As mentionned Tomerikoo
a = 1
b = l + m
c = l * m
I found the following code in my search to improve my codes for numerical analysis:
from math import sqrt
def RK4(f):
return lambda t, y, dt: (
lambda dy1: (
lambda dy2: (
lambda dy3: (
lambda dy4: (dy1 + 2 * dy2 + 2 * dy3 + dy4) / 6
)(dt * f(t + dt, y + dy3))
)(dt * f(t + dt / 2, y + dy2 / 2))
)(dt * f(t + dt / 2, y + dy1 / 2))
)(dt * f(t, y))
def theory(t):
return (t**2 + 4)**2 / 16
dy = RK4(lambda t, y: t * sqrt(y))
t, y, dt = 0., 1., .1
while t <= 10:
if abs(round(t) - t) < 1e-5:
print("y(%2.1f)\t= %4.6f \t error: %4.6g" % (t, y, abs(y - theory(t))))
t, y = t + dt, y + dy(t, y, dt)
Now, the program works fine and can see the overall algorithm of the program. But i can't understand how does the lambda nesting works. If i understand correctly all the dyN in RK4 are functions that are defined inside as they are needed for this ODE-solving method. But i don't know how the inner lambdas use the outer lambdas in their definition. Perhaps I'm not understanding the lambda syntax correctly.
What happens here is that lambda functions are defined and immediately called. First, realise that the following is just a complicated way of calculating the square of y:
( lambda x:
x**2
)( y )
The nesting in turn passes wraps another lambda around such a construction to modify its argument. Again, the following would be a complicated way to calculate the square of the sine of w, i.e., (math.sin(w))**2
( lambda z: (
lambda x: x**2
)(math.sin(z))
) (w)
So, the way to read this is to apply the steps from bottom to top to each other.
Writing the lambda-construction from your example with normal functions and without nested calls, it becomes:
def step_5(f,dy1,dy2,dy3,dy4):
return (dy1 + 2 * dy2 + 2 * dy3 + dy4) / 6
def step_4(f,dy1,dy2,dy3):
return step_5( dy1,dy2,dy3, dt * f(t + dt, y + dy3) )
def step_3(f,dy1,dy2):
return step_4( dy1,dy2, dt * f(t + dt / 2, y + dy2 / 2) )
def step_2(f,dy1):
return step_3( dy1, dt * f(t + dt / 2, y + dy1 / 2))
def RK4(f):
return step_2( dt * f(t, y) )
From there, it is only a short step to a readably written Runge–Kutta method.
I'm trying to fit a piecewise function with absolute values using Numpy.
The mathematical function is
x < p[1]: y = 1 + p[0] * abs((size + x - p[1]) / size - size / 2)
x >= p[1]: y = 1 + p[0] * abs((x - p[1]) / size - size / 2)
Here's my Python function:
fitfunc = lambda p, x: \
x < p[1] and\
1 + p[0] * abs((data['n1'].size + x - p[1]) / data['n1'].size - data['n1'].size / 2) or\
1 + p[0] * abs((x - p[1]) / data['n1'].size - data['n1'].size / 2)
Though, I'm getting the error:
The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
However, any and all evaluate an entire list to a single boolean value.
More info:
I've used lambdas to fit data to a sine wave by using the following:
fitfunc = lambda p, x: 1 + p[0] * sin(pi * x / data['n1'].size + p[1])
errfunc = lambda p, x, y: fitfunc(p, x) - y # Distance to the target function
Then in a loop:
data = np.genfromtxt(dataFileName, names=('n1', 'n2'))
xAxisSeries = scipy.linspace(0., data['n1'].max(), data['n1'].size)
p0 = [489., 123.] # Initial guess for the parameters
p1, success = scipy.optimize.leastsq(errfunc, p0[:], args=(xAxisSeries, data['n2']))
#time says which points from the sine wave will be plotted
time = scipy.linspace(0., data['n1'].max(), 100)
pylab.plot(time, fitfunc(p1, time), 'r-')
I'm trying to use a lambda function because optimize.leastsq requires one. I'm using the exact same code with the exception of fitfunc being changed.
The code above does not look idiomatic and is making life harder than it should be. :)
If you're trying to define a function and give it a name at the same time, the conventional approach is to use def, not lambda.
fitfunc = lambda p, x: ... ## you're making a named function, so just do...
def fitfunc(p, x): ...
And once you have that, you don't have to simulate short-circuiting branches with 'and' and 'or': you can just use if. You're getting into trouble trying to simulate if.
Truely speaking, it is not clear what you are trying to do with your lambda function.
But maybe it is the time of the day on my side of the globe...
In anycase, do note, that any(somelist) and np.array().any() are the same, but can be called differently.
In [2]: a=np.ones(4)
In [3]: a
Out[3]: array([ 1., 1., 1., 1.])
In [4]: a.any()
Out[4]: True
In [8]: a[1]=0
In [9]: a.all()
Out[9]: False
In [11]: somelist=["1","1","a","3"]
In [12]: any(somelist)
Out[12]: True
Do note also comment, how do you call this function? Can you please post more code?
Use def and scipy.optimize.curve_fit().
import scipy.optimize as so
def fitfunc(p, x):
'''Define fit function'''
if x < p[1]:
return 1 + p[0] * abs((data['n1'].size + x - p[1]) / data['n1'].size - data['n1'].size / 2)
else:
return 1 + p[0] * abs((x - p[1]) / data['n1'].size - data['n1'].size / 2)
popt, pcov = so.curve_fit(fitfunc, x, y)