I have a function defined that calculates the minimum of a function like x^2. I want to define a function that would calculate the maximum of a function by calculating the minimum of a similar function by multiplying through by negative one.
def myf(g):
return -(g+1.3)**2+5
def maximize(f,low,high,tol):
return minimize(-1*f,low,high,tol)
Is there a way to do this? When I try what I have I get the following error:
TypeError: unsupported operand type(s) for *: 'int' and 'function'
minimize is defined as such:
def minimize(f,low,high, tol):
if low>high:
c=low; a=high
a=float(a); c=float(c);
else:
a=float(low); c=float(high);
b=a+(c-a)*.618033
fa=f(a); fc=f(c)
fb=f(b);
if fb>fa or fb>fc: return maximize(f,low,high,tol)
while abs(a-c)>tol:
d=a+(c-b);
fd=f(d);
if d<b:
if fb<fd:
a=d; fa=fd;
else:
c=b; b=d
fc=fb; fb=fd
else:
if fd<fb:
a=b; fa=fb;
b=d; fb=fd
else:
c=d; fc=fd
return (a+c)/2.
Looking for a python code only solution.
You can't multiply a function with a number. Instead, construct a new function that uses the old one and multiplies the result (and not the function itself) with a number:
def maximize(f,low,high,tol):
return minimize(lambda x: -f(x),low,high,tol)
There are several ways to do this. The most straightforward is to "wrap" your function into another function. You can use lambda: new_f = lambda x: -f(x). In case you are not familiar with lambda's, this is a shortcut for
def new_f(x):
return -f(x)
Maybe you should be using scipy.optimize?
http://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html
Related
Consider the following Python code
def Hubble_a(a):
...
return
def t_of_a(a):
res = np.zeros_like(a)
for i,ai in enumerate(a):
t,err = quad(lambda ap : 1.0/(ap*Hubble_a(ap)),0,ai)
res[i] = t
return res
a = np.logspace(-8,1,100)
What I want to do is to define a function Hubble_a(a) that gives the derivative of a divided by a, in order to integrate over it with quad. I tried to define it in this way:
def Hubble_a(a):
da = diff(a,1)
da_over_a = da/a
return da_over_a
where diff is the FFT derivative imported from scipy.fftpack. Then, if I execute t_of_a(a) I get a object of type 'float' has no len() error, presumably because quad doesn't take arrays? However I don't think this definition makes any sense in the first place because I want to pass a function such that lambda maps to 1.0/(ap*Hubble_a(ap) and know I'm passing the derivative of an array instead of a function that can then by integrated over. So I'm looking for help on how to implement a function that maps to something like (da/dt)/a.
If I use 2 np arrays as x,y input into the following expression...
out = np.exp(3(x-4)-0.0001*y)
...I get "TypeError: 'int' object is not callable
If I use the same as function and call this function with a curve fit I get a similiar error:
def func(X, a, b):
x,y = X
return np.exp(a(x-4)-b*y)
Here I get:'numpy.float64' object is not callable
What am I doing wrong? It's working with others type of functions that don't use exp.
out = np.exp(3(x-4)-0.0001*y)
The problem in this expression is that the np.exp() function takes one argument but you passed 2. I don't know this is the best solution but instead of this you can try:
operations = 3*(x-4) - (0.0001*y)
out = np.exp(operations)
I need to write a python function called 'concat' that takes any two functions as input, and returns a function, which is the concatenated function of the two input functions (i.e. it takes f1 and f2, and returns f1◦f2).
I tried this:
def concat(f1,f2):
return f1(f2)
So for example, if f1 and f2 are:
def f1(x):
return x+2
def f2(x):
return x*2
then, concat(f1,f2) should return: (x*2)+2
I want to be able to use it like this:
a = concat(f1,f2)
a(5)
But I get an error:
TypeError: unsupported operand type(s) for +: 'function' and 'int'
I know I can define the function like this:
def concat(f1,f2,x):
return f1(f2(x))
But that is not what I want; I want to be able to create instances of the concat function, which then can be called with any x.
You need to return a new "wrapper" function. One option is to use a lambda expression:
def concat(f1, f2):
return lambda x: f1(f2(x))
DOCS: https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions
I think what you want is a closure.
def concat(f1, f2):
def f3(x):
return f1(f2(x))
return f3
Functions in Python are considered first class objects. This allows them to be created and manipulated like normal variables. In this case concat is constructing a new function that composes two functions.
The second property being used here is lexical scoping. The new function retains access to the local variables where it was defined not where it is executed. This allows the returned function to be run anywhere without losing access to the composite functions.
Here's a possible solution to compose more than two functions. Using a closure to loop through the functions and use the previous function's result as argument for the next one:
def compose(*fns):
def F(x):
for fn in fns[::-1]:
x = fn(x)
return x
return F
Then define your composition and call:
>>> F = compose(f1, f2, lambda x: x+1)
>>> F(4)
12 # f1(f2(f3(x)))
I'm wondering, how could I use a function that I've already defined inside another function? For example, I have a function f(n). Then I want to create a function g(n) such that it returns f(n)*2.
I'm trying to learn Python and I already know how to use some basic functions, then I tried to make a program to calculate the Greatest Common Divisor of two numbers. I created that function. I called it gcd(a,b), and it returns the GCD of a and b. It worked very well!
Then I want to reuse this function to calculate the Least Common Multiple of a and b.
I used the following code:
def lcm(a,b):
u=gcd(a,b)
v=a*b/u
print(v)
Using the fact that lcm(a,b)*gcd(a,b)=a*b I expect, with this code, that the output to be the LCM of a and b. But when I run the code and use the defined function I get this:
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
lcm(2,2)
File "C:/Users/(my user name)/AppData/Local/Programs/Python/Python37/euclides.py", line 55, in lcm
v=a*b/u
TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'
What does it means and how to solve it?
Change it to return the result rather than just print it:
def lcm(a,b):
u=gcd(a,b)
v=a*b/u
return v
Without the return, it will print the result, then implicitly return None.
You need to make the same change to your gcd function in order for the call to work as intended (it looks like your gcd function is returning None). Also note that in Python 3, gcd is available as math.gcd.
As the TypeError suggests, the error comes from the v=a*b/u line where u is supposed to be the return value from gcd().
It seems that the function gcd() is not returning any value. You need to add return from the gcd() function which you haven't included. As a pseudo code, do something like
def gcd(a, b):
# var = Do some stuff
return var
def lcm(a,b):
u=gcd(a,b)
v=a*b/u
return v
a = # some value
b = # some value
print (lcm(a, b))
You can use different structure also:
class GCD_model:
def gcd(a, b):
# var = Do some stuff
return var
def lcm(a,b, model):
u=model.gcd(a,b)
v=a*b/u
return v
a = # some value
b = # some value
model = GCD_model()
print (lcm(a, b, model))
I'm looking to build a generic object for curve fitting, where I define parameter names, values and bounds. Sometimes, I want to use the incoming data to help define the bounds using a function (min, max, etc.).
Here is the object:
class CurveFitObject(object):
def __init__(self,paramList,growthEquation):
self.paramList = paramList
self.gmod = Model(growthEquation)
def calcCurveFit(data):
for param in self.paramList:
self.gmod.set_param_hint(self.paramList['name'],
value=self.paramList['value'](data),
min=self.paramList['min'](data),
max=self.paramList['max'](data))
Here I am trying to use np.min(data) as my guess, 0.975 * np.min(data) as my lower bound, and 1.025 * np.min(data) as my upper bound.
def growthEquation(self, t, A): return A
keys = ['name','guess','min','max','vary']
logisticGrowth = CurveFitObject(
[dict(zip(keys,['A',np.min,0.975*np.min,1.025*np.min,True])),
growthEquation
)
I get the following error: TypeError: unsupported operand type(s) for *: 'float' and 'function'
which makes sense since it's trying to do math on the function 0.975*np.min rather than 0.975*np.min(data).
What is the best way to implement this behavior? If any?
It looks like you want to create a wrapper for an existing function. For example, you have:
0.975*np.min
But this doesn't work, since it's trying to multiply a float times a function. You can create a new function inline by using:
lambda data: 0.957*np.min(data)
This is probably what you're looking for. It's equivalent to defining a named function:
def myfunc(data):
return 0.957*np.min(data)
and then using myfunc. The difference is that the lambda syntax creates an anonymous function that can be defined inline.