optimize.curve_fit: how to bound one parameter respective to another? - python

When doing (ad hoc example)
from scipy import optimize
def fit_func(x, a, b):
return a*x + b
optimize.curve_fit(fit_func, x_data, y_data)
how can I put bounds like a>b? I know the option bounds, but it appears it does accept only explicit numbers.
Maybe some if in the definition of fit_func?

You can try with a workaround, instead of defining the function as:
def fit_func1(x, a, b):
return a*x + b
with constraint a>b, you can do:
def fit_func2(x, this_much_a_is_bigger_than_b, b):
return (a+this_much_a_is_bigger_than_b)*x + b
with constraint this_much_a_is_bigger_than_b > 0, 0 being an explicit number, and fit_func2 function is equivalent to the fit_func1 from a mathematical perspective.
Then you can have:
a = b + this_much_a_is_bigger_than_b
b = b

Curce_fit only supports box constraints (via least_squares). There are workarounds, but I'd rather change variables to e.g a and b-a

Related

scale translate function with python decorator

I have a list of single parameter functions in python to which I would like to apply the same scaling/translation operation.
The scale/translation for a function f(x) would be as follows:
f'(x, a, b, c, d) = a + b* f( c*(x - d) )
So for example if my original function is defined as:
f(x) = 3*x
I would like to modify it to be:
f'(x, a, b, c, d) = a + b * (3*(c*(x - d)))
Ideally using a decorator (or some other reusable operation that I can apply to each function in the list).
Is there a pythonic way to achieve this such that every transformation doesn't need to be hardcoded for each function I have?
Apologies if the question is unclear - thanks in advance for any suggestions.
def f(x):
return 3*x
def makeFPrime(func):
def inner(x, a, b, c, d):
return a + b * (3*(c*func(x-d)))
return inner
This gives for example:
f2 = makeFPrime(f)
f2(2,1,1,1,2)
1
f2(2,1,1,1,0)
19
Alternatively, use makeFPrime as a decorator:
def makeFPrime(func):
def inner(x, a, b, c, d):
return a + b * (3*(c*func(x-d)))
return inner
#makeFPrime
def f(x):
return 3*x
Then f(2,1,1,1,2) returns 1

Evaluate Derivative of Function at a Point Python 2.7

I have the following function:
import sympy as sp
def inverted(q, m, a, nu):
return (-1)**(m+1)*(a/m)**m*sp.exp(m)*q**(-nu)*sp.diff(1/(sp.sqrt(a**2+q**2))*(sp.sqrt(a**2+q**2)-a)**(nu), a, m+1)
I want to define some lambda function such that
f100 = lambda a, q: inverted(q, 100, a, 0)
However, when I try to examine
q = sp.symbols('q')
f100(1000.0, q)
I get the following output:
ValueError:
Can't calculate 101st derivative wrt 10.
Obviously, what is happening is when I call f100(1000.0, q), the function refers back to inverted and the issue arises. I was hoping for a way around this.
Seems like you have to make a a variable first so diff works. It doesn't work if you fix a before (I think because you differentiate with respect to a). You can substitute a with 1000 afterwards.
import sympy as sp
def inverted(q, m, a, nu):
return (-1)**(m+1)*(a/m)**m*sp.exp(m)*q**(-nu)*sp.diff(1/(sp.sqrt(a**2+q**2))*(sp.sqrt(a**2+q**2)-a)**(nu), a, m+1)
f100 = lambda a, q: inverted(q, 100, a, 0)
q, a = sp.symbols('q, a')
print(f100(a, q).subs(a, 1000))

Numpy: different values when calculating a sum of a sequence

I'm using scipy.integrate's odeint function to evaluate the time evolution of to find solutions to the equation
$$ \dot x = -\frac{f(x)}{g(x)}, $$
where $f$ and $g$ are both functions of $x$. $f,g$ are given by series of the form
$$ f(x) = x(1 + \sum_k b_k x^{k/2}) $$
$$ g(x) = 1 + \sum_k a_k (1 + k/2) x^{k/2}. $$
All positive initial values for $x$ should result in the solution blowing up in time, but they aren't...well, not always.
The coefficients $a_n, b_n$ are long polynomials, where $b_n$ is dependent on $x$ in a certain way, and $a_n$ is dependent on several terms being held constant.
Depending on the way I compute $g(x)$, I get very different behavior.
The first way I tried is as follows. 'a' and 'b' are 1x8 and 1x9 numpy arrays. Note that in the function g(x, a), a is multiplied by gterms in line 3, and does not appear in line 2.
def g(x, a):
gterms = [(0.5*k + 1.) * x**(0.5*k) for k in range( len(a) )]
return = 1. + np.sum(a*gterms)
def rhs(u,t)
x = u
a, b = An(), Bn(x) #An() and Bn(x) are functions that return an array of coefficients
return -f(x, b)/g(x, a)
t = np.linspace(.,.,.)
solution = odeint(rhs, <some initial value>, t)
The second way was this:
def g(x, a):
gterms = [(0.5*k + 1.) * a[k] * x**(0.5*k) for k in range( len(a) )]
return = 1. + np.sum(gterms)
def rhs(u,t)
x = u
a, b = An(), Bn(x) #An() and Bn(x) are functions that return an array of coefficients
return -f(x, b)/g(x, a)
t = np.linspace(.,.,.)
solution = odeint(rhs, <some initial value>, t)
Note the difference: using the first method, I stuck the array 'a' into the sum in line 3, whereas using the second method, I suck the values of 'a' into the list 'gterms' in line 2 instead.
The first method gives the expected behavior: solutions blow up positive x. However, the second method does not do this. The second method gives a bifurcation for some x0 > 0 that acts as a source. For initial conditions greater than x0, solutions blow up as expected, but initial conditions less than x0 have the solutions tending to 0 very slowly.
Something else of note: in the rhs function, if I change it from
def rhs(u,t)
x = u
...
return .
to
def rhs(u,t)
x = u[0]
...
return .
the same exact change occurs
So my question is: what is the difference between the two different methods I used? I can't tell for the life of me what is actually going on here. Sorry for being so verbose.

SymPy: Evaluate given expression with given variables

I have a sympy expression involving two variables a, b. I would now like to evaluate this expression for specific values of a and b. Using a lambda like
import sympy
def get_expression(a, b):
# Complex function with a simple result. I have no control here.
return a*b + 2
a = sympy.Symbol('a')
b = sympy.Symbol('b')
z = get_expression(a, b)
f = lambda a, b: z
print(f(1, 1))
only gives
a*b + 2
though.
Any hints?
Turns out that lambdify is what I need:
f = sympy.lambdify([a, b], z)
print(f(1, 1))

SymPy: Swap two variables

In an expression like
import sympy
a = sympy.Symbol('a')
b = sympy.Symbol('b')
x = a + 2*b
I'd like to swap a and b to retrieve b + 2*a. I tried
y = x.subs([(a, b), (b, a)])
y = x.subs({a: b, b: a})
but neither works; the result is 3*a in both cases as b, for some reason, gets replaced first.
Any hints?
There is a simultaneous argument you can pass to the substitution, which will ensure that all substitutions happen simultaneously and don't interfere with one another as they are doing now.
y = x.subs({a:b, b:a}, simultaneous=True)
Outputs:
2*a + b
From the docs for subs:
If the keyword simultaneous is True, the subexpressions will not be evaluated until all the substitutions have been made.

Categories

Resources