overflow in exp using python scipy.optimize.basinhopping - python

I am using scipy.optimize.basinhopping in order to fit a simple exponential function (aexp(-btime)) to real data. I try to have appropriate initial guesses (for a and b) but in some iterations (for some values basinhopping guesses) "overflow in exp" occurs. I know that it is because of a very large answer to be calculated by exp. By the way the result is something absolutely wrong.
Is there anyway to ask the code to ignore those error containing guesses in order to prevent wrong results in output?
+ time goes from 0 to something around e+06
Thanks for your care and help

here is my code. after running, I get overflow error for some values for bk, so the resulting value for ret is absolutely wrong, something far far from the correct answer. :(
def model(bk):
s = 0
realData = data()
modelData = []
modelData.append(realData[0])
for time in range(len(realData) - 1):
x = realData[0] * np.exp((bk[0] * np.exp(bk[1]*time))*time)
y = 1 - realData[0] + x
i = x / y
modelData.append(i)
s+=np.abs(i-realData[time])
return(s)
def optimize():
bk0 = [1,-1]
minimizer_kwargs = {"method" : "BFGS"}
ret = basinhopping(model, bk0, minimizer_kwargs=minimizer_kwargs, niter=100)
print(ret)
optimize()

Related

Minimize function with scipy

I'm trying to do one task, but I just can't figure it out.
This is my function:
1/(x**1/n) + 1/(y**1/n) + 1/(z**1/n) - 1
I want that sum to be as close to 1 as possible.
And these are my input variables (x,y,z):
test = np.array([1.42, 5.29, 7.75])
So n is the only decision variable.
To summarize:
I have a situation like this right now:
1/(1.42**1/1) + 1/(5.29**1/1) + 1/(7.75**1/1) = 1.02229
And I want to get the following:
1/(1.42^(1/0.972782944446024)) + 1/(5.29^(1/0.972782944446024)) + 1/(7.75^(1/0.972782944446024)) = 0.999625
So far I have roughly nothing, and any help is welcome.
import numpy as np
from scipy.optimize import minimize
def objectiv(xyz):
x = xyz[0]
y = xyz[1]
z = xyz[2]
n = 1
return 1/(x**(1/n)) + 1/(y**(1/n)) + 1/(z**(1/n))
test = np.array([1.42, 5.29, 7.75])
print(objectiv(test))
OUTPUT: 1.0222935270013889
How to properly define a constraint?
def conconstraint(xyz):
x = xyz[0]
y = xyz[1]
z = xyz[2]
n = 1
return 1/(x**(1/n)) + 1/(y**(1/n)) + 1/(z**(1/n)) - 1
And it is not at all clear to me how and what to do with n?
EDIT
I managed to do the following:
def objective(n,*args):
x = odds[0]
y = odds[1]
z = odds[2]
return abs((1/(x**(1/n)) + 1/(y**(1/n)) + 1/(z**(1/n))) - 1)
odds = [1.42,5.29,7.75]
solve = minimize(objective,1.0,args=(odds))
And my output:
fun: -0.9999999931706812
x: array([0.01864994])
And really when put in the formula:
(1/(1.42^(1/0.01864994)) + 1/(5.29^(1/0.01864994)) + 1/(7.75^(1/0.01864994))) -1 = -0.999999993171
Unfortunately I need a positive 1 and I have no idea what to change.
We want to find n that gets our result for a fixed x, y, and z as close as possible to 1. minimize tries to get the lowest possible value for something, without negative bound; -3 is better than -2, and so on.
So what we actually want is called least-squares optimization. Similar idea, though. This documentation is a bit hard to understand, so I'll try to clarify:
All these optimization functions have a common design where you pass in a callable that takes at least one parameter, the one you want to optimize for (in your case, n). Then you can have it take more parameters, whose values will be fixed according to what you pass in.
In your case, you want to be able to solve the optimization problem for different values of x, y and z. So you make your callback accept n, x, y, and z, and pass the x, y, and z values to use when you call scipy.optimize.least_squares. You pass these using the args keyword argument (notice that it is not *args). We can also supply an initial guess of 1 for the n value, which the algorithm will refine.
The rest is customization that is not relevant for our purposes.
So, first let us make the callback:
def objective(n, x, y, z):
return 1/(x**(1/n)) + 1/(y**(1/n)) + 1/(z**(1/n))
Now our call looks like:
best_n = least_squares(objective, 1.0, args=np.array([1.42, 5.29, 7.75]))
(You can call minimize the same way, and it will instead look for an n value to make the objective function return as low a value as possible. If I am thinking clearly: the guess for n should trend towards zero, making the denominators increase without bound, making the sum of the reciprocals go towards zero; negative values are not possible. However, it will stop when it gets close to zero, according to the default values for ftol, xtol and gtol. To understand this part properly is beyond the scope of this answer; please try on math.stackexchange.com.)

How do you make a generator release a value?

Currently I am trying to make a binomial coefficient using Python. So I tried to create 3 different generators, one for n!, k! and (n-k)!. Since I know return will not give back a value but instead a location of where the memory is stored, I tried to use yield. But if i put yield as below, it somehow gave another memory being stored rather than dividing each other in the ans formula. I'm still confused because I assume it is my indentation but as I fiddle with it, it just keep giving error messages. Can anyone help to modify this such that it releases a value? I just want to make the generator spit out values so that they can be used for the ans formula in the last line.
def binom_coeff(n,k):
def fact(n):
basic = 1
for i in range(1,n+1):
basic = basic * i
yield basic
def fact(k):
basic_3 = 1
for j in range(1,j+1):
basic_3 = basic_3 * j
yield basic_3
def fact_d(n,k):
basic_2 = 1
for m in range(1, n-k+1):
basic_2 = basic_2 * m
yield basic_2
ans = basic / (basic_3 * basic_2)
return ans
I don't think you want a generator here. Just return basic, etc. And those statements should be inside the functions. Currently, the yield statements are not.
Even if you did want to use a generator, you never call the functions. Also, there are a few typos.
def binom_coeff(n,k):
def fact(n):
basic = 1
for i in range(1, n+1):
basic = basic * i
return basic
ans = fact(n) / (fact(k) * fact(n-k))
return ans

Is there a convenient way to express the continuous relaxation of a MIP using cvxpy?

I want to solve a (convex) mixed integer program as well as its continuous relaxation using cvxpy. Is there a way to use the same implementation of the objective and the constraints for both calculations?
As an example, take a look at the MIP example problem from the cvxpy website with some added constraint 'x[0]>=2':
np.random.seed(0)
m, n= 40, 25
A = np.random.rand(m, n)
b = np.random.randn(m)
# Construct a CVXPY problem
x = cp.Variable(n, integer=True) # x is an integer variable
obj = cp.sum_squares(A#x - b)
objective = cp.Minimize(obj)
constraint = [x[0] >= 2]
prob = cp.Problem(objective, constraint)
prob.solve()
print("The optimal value is", prob.value)
print("A solution x is")
print(x.value)
x = cp.Variable(n) # Now, x is no longer an integer variable but continuous
obj = cp.sum_squares(A#x - b) # I want to leave out this line (1)
constraint = [x[0] >= 2] # I want to leave out this line (2)
objective = cp.Minimize(obj)
prob = cp.Problem(objective, constraint)
prob.solve()
print("The optimal value is", prob.value)
print("A solution x is")
print(x.value)
When leaving out line (2), the problem is solved without the constraint. When leaving out line (1), the mixed integer problem is solved (so, changing 'x' to a continuous variable did not have any effect).
I want to avoid reimplementing the objective function and constraints because a missed copy and paste may lead to weird, hard-to-find errors.
Thank you for your help!
Edit: Thank you, Sascha, for your reply. You are right, outsourcing the model building solves the problem. So
class ModelBuilder:
m, n = 40, 25
A = np.random.rand(m, n)
b = np.random.randn(m)
def __init__(self, solve_continuous):
np.random.seed(0)
if solve_continuous:
self.x = cp.Variable(self.n)
else:
self.x = cp.Variable(self.n, integer=True)
#staticmethod
def constraint_func(x):
return [x[0] >= 2]
def objective_func(self, x):
return cp.sum_squares(self.A#x - self.b)
def build_problem(self):
objective = cp.Minimize(self.objective_func(self.x))
constraint = self.constraint_func(self.x)
return cp.Problem(objective, constraint)
# Construct and solve mixed integer problem
build_cont_model = False
MIP_Model = ModelBuilder(build_cont_model)
MIP_problem = MIP_Model.build_problem()
MIP_problem.solve()
print("The optimal value is", MIP_problem.value)
print("A solution x is")
print(MIP_Model.x.value)
# Construct and solve continuous problem
build_cont_model = True
Cont_Model = ModelBuilder(build_cont_model)
Cont_problem = Cont_Model.build_problem()
Cont_problem.solve()
print("The optimal value is", Cont_problem.value)
print("A solution x is")
print(Cont_Model.x.value)
works just as expected. Since I did not have this simple idea, it shows me that I do not yet understand the concept of applying a cvxpy.Variable to an expression.
In my first attempt, I defined variable x and used it when defining obj. Then, I changed the value of x (one line before (1)). I thought that obj was linked to x by a pointer or something similar, so that it would change its behavior, as well. Apparently, this is not the case.
Do you know any resources that could help me understand this behavior? Or is it obvious to anyone that is familiar with Python? Then, where could I learn about it?

Speed of different data structures in Python

I have a piece of code I need to run, however, it is taking so long. I estimate it will take a minimum of 2 hours to run and at most 100 hours. As you can see, I would like to speed this up.
My code is as follows:
#B1
file = open("/home/1015097/Downloads/B1/tour5.txt", "r").readlines()
# This is a very large file. You can find it on http://codemasters.eng.unimelb.edu.au/bit_problems/B1.zip
# It is named tour5.txt, you can also find the question I am trying to solve there.
racers = [int(file[0].split()[0]) / float(x) for x in file[0].split()[1::]]
print("hi")
def av(race):
race = race.split()
j = 0
while j != len([float(race[0]) / float(x) for x in race[1::]]):
racers[j] = [float(race[0]) / float(x) for x in race[1::]][j] + racers[j]
j += 1
print(j)
print("yay...")
for i in range(1, len(file)):
print("yay")
av(file[i])
print("yaaay")
a = min(racers)
del(racers[racers.index(min(racers))])
b = min(racers)
c = b-a
h = int(c)
c-=h
m = int(c * 60)
c-=m/60
s = round(c * 60 * 60)
print(str(h) + "h" + str(m) + "m" + str(s) + "s")
We are currently coming first in Australia for the Code Bits contest and would not like to drop our perfect score. The random print statements were so that we could tell if the code was actually running, they are essentially checkpoints. the number that is printed out is the racer number, there are at least 3000 racers, we do not know exactly.
I would start with changing:
while j != len([float(race[0]) / float(x) for x in race[1::]]):
racers[j] = [float(race[0]) / float(x) for x in race[1::]][j] + racers[j]
into
while j != len(race) - 1:
racers[j] += float(race[0]) / float(race[j])
Avoid loops like the plague. Vectorize everything. Use numpy, etc. If you have to, even look into Cython. But most importantly, vectorize.
The av() function is probably the part where your code is taking the most time (btw, it would be a good idea to profile the code at various points, figure out the most taxing process and focus on vectorizing it). Also, try to minimize the number of initializations. If you can, create an object only once and for all.
Below is how I would change up the function.
import numpy as np
racers = np.array(racers)
def av(race, racers):
race = race.split()
race_float = np.array(len([float(race[0]) / float(x) for x in race[1::]]))
racers += race_float
return racers
Also, please refrain from:
Using print for debugging. You have a built-in logging module. Use it.
Using globals. Just pass them into functions as arguments and return the new object instead of directly modifying a global object.
I think you should be looking at numpy arrays instead of lists. Thereby you can avoid the loops and obtain close to c -speed. This problem is easily applicable to that. And by the way why not store anything in float64 or float32 so there is no conversion of datatypes. Code example not fully portable. It is a schoolwork and I should not do it for you:
import numpy as np
racer=np.array(racer) # Will work for 1 d lists and for 2-d lists with same lenght
racer_time=racer/time # diving a vector by a scalar is easy

Compute cosine without import math in python

I have a general idea of what to do, but my code is a mess and I'm having some trouble writing the algorithm in python for
cos(x)=1-(x^2)/2!+(x^4)/4!-(x^6)/6!+...
where x is in radians, computing cos(x) after 20 terms using while loops. So far what I've written is
x = float(input("Enter a value for x in degrees."))
x = (x*3.14159)/180
num_of_terms = 0
num = 1.0 ##numerator
y = 1.0
cosx = 1.0
while num_of_terms<1:
num_of_terms+=1
cosx = (num/y)
while num_of_terms>=1 and num_of_terms<=20:
num_of_terms+=1
num = num*(x*x)
y = y*num_of_terms*(num_of_terms-1)
if num_of_terms%2==0:
cosx = cosx+(-num/y)
else:
cosx = cosx+(num/y)
print(cosx)
I don't know how close I even am to being correct (I know it's wrong in at least some places so I can't properly check using math.cos) but the main question I have is how to switch from positive --> negative each term. The assignment states that I cannot use exponentiation operators, and before I was trying to do something like
x = float(input("Enter a value for x in degrees."))
x = (x*3.14)/180
num_of_terms = 0
y = 0
z = 1
cosx = ((-1)**(z-1))*((x**z)/(y))
so that the sign would switch for every other term. Now I have (as you can see above)
if num_of_terms%2==0:
cosx = cosx+(-num/y)
else:
cosx = cosx+(num/y)
which is incorrect, or at least the output I'm getting is incorrect.
You can handle the sign quite simply:
sign = -1
while num_of_terms <= 20:
sign = -sign
...
cosx += sign * num/y
You also have a structure problem in your loops: the first loop will terminate after one iteration ... except you've properly prevented it from getting back there. This is poor use of a loop.
Just initialize your variables before the loop, and then proceed as expected. Since you know how many times to iterate, use a for instead of a while.
cosx = (num/y)
for num_of_terms in range(1, 21):
...
You will find other computational problems in your code. Print out values each time through the loop to help track your execution and computations. At the start, just go through 3 or 4 times instead of 20.
For the factorial, keep a running product: it's like a running sum, except that you initialize it at 1, and multiply each time through the loop.
Okay; stick with the while. Now, manage your loop index and computational index. If you're doing term #1, what should the exponent be? What numbers do you multiply into y? Now identify the same values for term #2 and term #3.
More directly, stick in a print statement to track num_of_terms, y, and cosx. When you're doing term #3, what is y? It should be 4! or 6! (depending on how you number your terms), but it's not. Where did you go wrong?
Your problem is in the computation of the factorial. You're multiplying by num_of_terms, which only increments by one each time through the loop - you need something that changes by 2 each time through the loop. At least you're correctly multiplying both that number and the number-1.

Categories