Gurobi objective function - gurobi

I am trying to convert an objective function from scipy to Gurobi as follows but getting "unsupported operand type(s) for ** or pow(): 'gurobipy.LinExpr' and 'float'".
Any idea how I could re-write the below? Thanks in advance.
from gurobipy import *
import scipy.optimize as optimize
price = 95.0428
par = 100.0
T = 1.5
coup = 5.75
freq = 2
guess = 0.05
freq = float(freq)
periods = T * freq
coupon = coup / 100. * par / freq
dt = [(i + 1) / freq for i in range(int(periods))]
#coverting the below scipy.optimize to Gurobi
#ytm_func = lambda y: sum([coupon / (1 + y / freq) ** (freq * t) for t in dt]) + (par / (1 + y / freq) ** (freq * T)) - price
#optimize.newton(ytm_func, guess)
m = Model()
y = m.addVar(vtype=GRB.CONTINUOUS, name='y')
m.setObjective(quicksum([coupon / (1 + y / freq) ** (freq * t) for t in dt]) + (par / (1 + y / freq) ** (freq * T)) - price, GRB.MINIMIZE)
m.optimize()
m.printAttr('X')

Hi I think what you are trying to do is not supported by gurobi yet. Not at least as a quadratic programming.
First you have your variables in the denominator which is not advised / supported directly
Second what you are defining is not a quadratic problem. It is a polynomial problem. As far as I know gurobi currently supports only quadratic programs with expressions such as y*y
This is unconstrained problem so I wonder why you need gurobi. Scientific solvers deal with these problem pretty well using gradient decent, Newton and so on methods
I hope this helps

Related

Inequality constraints of convex relaxation with McCormick envelope

I have a nonconvex optimization problem for which I am calculating a lower bound using the McCormick envelope. Each bilinear term is replaced with an auxiliary variable which has the following constraints defined:
w_{ij} >= x_i^L * x_j + x_i * x_j^L - x_i^L * x_j^L
w_{ij} >= x_i^U * x_j + x_i * x_j^U - x_i^U * x_j^U
w_{ij} <= x_i^U * x_j + x_i * x_j^L - x_i^U * x_j^L
w_{ij} <= x_i^L * x_j + x_i * x_j^U - x_i^L * x_j^U
where
x_U <= x <= x_L
I am given a function taking in several arguments:
def convex_bounds(n,m,c,H,Q,A,b,lb,ub):
# n is the number of optimization variables
# m is the number of eq constraints
# H = positive, semidefinite matrix from objetcive function (n x n)
# Q is (mxn) x n
# A is m x n
# b is RHS of non linear eq constraints (m x 1)
# c,lb,ub are vectors size (n x 1)
......................................
# Create matrix B & b_ineq for inequality constraints
# where B*x <= b_ineq
B = np.eye(3)
b_ineq = np.array((10,10,10))
## these values would work in a scenario with no bilinear terms
My problem is that I don't know how to specify the inequality constraints matrix B and vector b_ineq. For this particular exercise my variables are x1, x2 and x3 with bounds 0 (x_L) and 10 (x_U). My bilinear terms are x_12 and x_23 (which will lead to auxiliary variables w_12 and w_23). How can I specify the known bounds (0 and 10) for x1,x2 and x3 and the calculated ones (as in the theory pasted above) in B and b_ineq?
I don't actually know how to proceed with this.

Numerically stable calculation of invariant mass in particle physics?

In particle physics, we have to compute the invariant mass a lot, which is for a two-body decay
When the momenta (p1, p2) are sometimes very large (up to a factor 1000 or more) compared to the masses (m1, m2). In that case, there is large cancellation happening between the last two terms when the calculation is carried out with floating point numbers on a computer.
What kind of numerical tricks can be used to compute this accurately for any inputs?
The question is about suitable numerical tricks to improve the accuracy of the calculation with floating point numbers, so the solution should be language-agnostic. For demonstration purposes, implementations in Python are preferred. Solutions which reformulate the problem and increase the amount of elementary operations are acceptable, but solutions which suggest to use other number types like decimal or multi-precision floating point numbers are not.
Note: The original question presented a simplified 1D dimensional problem in form of a Python expression, but the question is for the general case where the momenta are given in 3D dimensions. The question was reformulated in this way.
With a few tricks listed on Stackoverflow and the transformation described by Jakob Stark in his answer, it is possible to rewrite the equation into a form that does not suffer anymore from catastrophic cancellation.
The original question asked for a solution in 1D, which has a simple solution, but in practice, we need the formula in 3D and then the solution is more complicated. See this notebook for a full derivation.
Example implementation of numerically stable calculation in 3D in Python:
import numpy as np
# numerically stable implementation
#np.vectorize
def msq2(px1, py1, pz1, px2, py2, pz2, m1, m2):
p1_sq = px1 ** 2 + py1 ** 2 + pz1 ** 2
p2_sq = px2 ** 2 + py2 ** 2 + pz2 ** 2
m1_sq = m1 ** 2
m2_sq = m2 ** 2
x1 = m1_sq / p1_sq
x2 = m2_sq / p2_sq
x = x1 + x2 + x1 * x2
a = angle(px1, py1, pz1, px2, py2, pz2)
cos_a = np.cos(a)
if cos_a >= 0:
y1 = (x + np.sin(a) ** 2) / (np.sqrt(x + 1) + cos_a)
else:
y1 = -cos_a + np.sqrt(x + 1)
y2 = 2 * np.sqrt(p1_sq * p2_sq)
return m1_sq + m2_sq + y1 * y2
# numerically stable calculation of angle
def angle(x1, y1, z1, x2, y2, z2):
# cross product
cx = y1 * z2 - y2 * z1
cy = x1 * z2 - x2 * z1
cz = x1 * y2 - x2 * y1
# norm of cross product
c = np.sqrt(cx * cx + cy * cy + cz * cz)
# dot product
d = x1 * x2 + y1 * y2 + z1 * z2
return np.arctan2(c, d)
The numerically stable implementation can never produce a negative result, which is a commonly occurring problem with naive implementations, even in double precision.
Let's compare the numerically stable function with a naive implementation.
# naive implementation
def msq1(px1, py1, pz1, px2, py2, pz2, m1, m2):
p1_sq = px1 ** 2 + py1 ** 2 + pz1 ** 2
p2_sq = px2 ** 2 + py2 ** 2 + pz2 ** 2
m1_sq = m1 ** 2
m2_sq = m2 ** 2
# energies of particles 1 and 2
e1 = np.sqrt(p1_sq + m1_sq)
e2 = np.sqrt(p2_sq + m2_sq)
# dangerous cancelation in third term
return m1_sq + m2_sq + 2 * (e1 * e2 - (px1 * px2 + py1 * py2 + pz1 * pz2))
For the following image, the momenta p1 and p2 are randomly picked from 1 to 1e5, the values m1 and m2 are randomly picked from 1e-5 to 1e5. All implementations get the input values in single precision. The reference in both cases is calculated with mpmath using the naive formula with 100 decimal places.
The naive implementation loses all accuracy for some inputs, while the numerically stable implementation does not.
If you put e.g. m1 = 1e-4, m2 = 1e-4, p1 = 1 and p2 = 1 in the expression, you get about 4e-8 with double precision but 0.0 with single precision calculation. I assume, that your question is about how one can get the 4e-8 as well with single precision calculation.
What you can do is a taylor expansion (around m1 = 0 and m2 = 0) of the expression above.
e ~ e|(m1=0,m2=0) + de/dm1|(m1=0,m2=0) * m1 + de/dm2|(m1=0,m2=0) * m2 + ...
If I calculated correctly, the zeroth and first order terms are 0 and the second order expansion would be
e ~ (p1+p2)/p1 * m1**2 + (p1+p2)/p2 * m2**2
This yields exactly 4e-8 even with single precision calculation. You can of course do more terms in the expansion if you need, until you hit the precision limit of a single float.
Edit
If the mi are not always much smaller than the pi you could further massage the equation to get
The complicated part is now the one in the square brackets. It essentially is sqrt(x+1)-1 for a wide range of x values. If x is very small, we can use the taylor expansion of the square root (e.g. like here). If the x value is larger, the formula works just fine, because the addition and subtraction of 1 are no longer discarding the value of x due to floating point precision. So one threshold for x must be choosen below one switches to the taylor expansion.

Percentage weighting given two variables to equal a target

I have a target of target = 11.82 with two variables
x = 9
y = 15
How do I find the percentage weighting that would blend x & y to equal my target? i.e. 55% of x and 45% of y - what function is most efficient way to calc a weighting to obtain my target?
Looking at it again, what I think you want is really two equations:
9x + 15y = 11.82
x + y = 1
Solving that system of equations is pretty fast on pen and paper (just do linear combination). Or you could use sympy to solve the system of linear equations:
>>> from sympy import *
>>> from sympy.solvers.solveset import linsolve
>>> x, y = symbols('x, y')
>>> linsolve([x + y - 1, 9 * x + 15 * y - 11.82], (x, y)) # make 0 on right by subtraction
FiniteSet((0.53, 0.47))
We can confirm this by substitution:
>>> 9 * 0.53 + 15 * 0.47
11.82

Is Romberg integration method implemented as weighted function values numerically correct?

I have to integrate expression f(x) * g(x) for many different functions f but just one g.
I want to integrate it as sum of weighted values of f(x) * g(x) instead of calculating the table. Note that in Python I may write:
sum(w[i] * f(x[i]) * g(x[i]) for i in range(2 ** k + 1))
as:
wg = [w[i] * g(x[i]) for i in range(2 ** k + 1)]
sum(wg[i] * f(x[i]) for i in range(2 ** k + 1))
where w[i] are weights of function values used by the Romberg method which may be calculated like:
import numpy as np
from scipy.integrate import romb
w = romb(np.eye(2 ** k + 1))
Is such implementation of Romberg method safe?
(The question has been also asked at CS: https://scicomp.stackexchange.com/questions/35469/is-romberg-integration-method-implemented-as-weighted-function-values-numericall)

Slew rate measuring

I have to measure slew rates in signals like the one in the image below. I need the slew rate of the part marked by the grey arrow.
At the moment I smoothen the signal with a hann window to get rid of eventual noise and to flatten the peaks. Then I search (starting right) the 30% and 70% points and calculate the slew rate between this two points.
But my problem is, that the signal gets flattened after smoothing. Therefore the calculated slew rate is not as high as it should be. An if I reduce smoothing, then the peaks (you can see right side in the image) get higher and the 30% point is eventually found at the wrong position.
Is there a better/safer way to find the required slew rate?
If you know between what values your signal is transitioning, and your noise is not too large, you can simply compute the time differences between all crossings of 30% and all crossings of 70% and keep the smallest one:
import numpy as np
import matplotlib.pyplot as plt
s100, s0 = 5, 0
signal = np.concatenate((np.ones((25,)) * s100,
s100 + (np.random.rand(25) - 0.5) * (s100-s0),
np.linspace(s100, s0, 25),
s0 + (np.random.rand(25) - 0.5) * (s100-s0),
np.ones((25,)) * s0))
# Interpolate to find crossings with 30% and 70% of signal
# The general linear interpolation formula between (x0, y0) and (x1, y1) is:
# y = y0 + (x-x0) * (y1-y0) / (x1-x0)
# to find the x at which the crossing with y happens:
# x = x0 + (y-y0) * (x1-x0) / (y1-y0)
# Because we are using indices as time, x1-x0 == 1, and if the crossing
# happens within the interval, then 0 <= x <= 1.
# The following code is just a vectorized version of the above
delta_s = np.diff(signal)
t30 = (s0 + (s100-s0)*.3 - signal[:-1]) / delta_s
idx30 = np.where((t30 > 0) & (t30 < 1))[0]
t30 = idx30 + t30[idx30]
t70 = (s0 + (s100-s0)*.7 - signal[:-1]) / delta_s
idx70 = np.where((t70 > 0) & (t70 < 1))[0]
t70 = idx70 + t70[idx70]
# compute all possible transition times, keep the smallest
idx = np.unravel_index(np.argmin(t30[:, None] - t70),
(len(t30), len(t70),))
print t30[idx[0]] - t70[idx[1]]
# 9.6
plt. plot(signal)
plt.plot(t30, [s0 + (s100-s0)*.3]*len(t30), 'go')
plt.plot(t30[idx[0]], [s0 + (s100-s0)*.3], 'o', mec='g', mfc='None', ms=10)
plt.plot(t70, [s0 + (s100-s0)*.7]*len(t70), 'ro')
plt.plot(t70[idx[1]], [s0 + (s100-s0)*.7], 'o', mec='r', mfc='None', ms=10 )
plt.show()