I have a function that I wish to optimize, but that is returning nans.
Here is the function (fnRestrictParams is a helper function):
def fnRestrictParams(vParams):
vRestrictedParams = vParams
vRestrictedParams[1] = exp(vParams[1])
vRestrictedParams[2] = exp(vParams[2]) / (1 + exp(vParams[2]))
return(vRestrictedParams)
def fnGASGaussianCopulaLikelihood(vParams, iT, mData):
dLL = 0 # initialize the likelihood at zero
vRestrictedParams = fnRestrictParams(vParams)
dOmega = vRestrictedParams[0]
dA = vRestrictedParams[1]
dB = vRestrictedParams[2]
dFactor = dOmega
dOmega = dOmega*(1 - dB)
vFactor = np.zeros(iT)
for t in range(iT):
# compute the copula parameters based on the factors
rho = (1 - exp(-dFactor))/(1 + exp(-dFactor))
rho2 = rho * rho
vFactor[t] = rho
# quantile functions
qu = sps.norm.ppf(mData[t, :])
x = qu[0] ** 2 + qu[1] ** 2
y = qu[0] * qu[1]
# get the log pdf of the copula, and its gradient with respect to the copula parameters
dLL += -0.5 * np.log(1 - rho2) - 0.5 * (rho2 * x - 2 * rho * y) / (1 - rho2)
# scaled score function
dSt = (2 / (1 - rho2)) * (y - rho - rho * (x - 2) / (1 + rho2))
# GAS recursion
dFactor = dOmega + dA * dSt + dB * dFactor
dLL = dLL/iT
return(-dLL)
The data to test this function is here.
I know that this function works correctly, because I have compared the output to an implementation available from the original authors (in another programming language).
# load the data
mData = np.loadtxt("./Data/Patton4filtered.csv",
skiprows=1, usecols = tuple(range(1, 4)), delimiter = ",")
# test the likelihood function
for x in np.arange(3.1, 4, .1):
print(fnGASGaussianCopulaLikelihood([x, -5, 5.0], mData.shape[0], mData[:, [0, 1]]))
However, when I try to optimize this function using scipy.optimize.minimize:
# optimize the function without the gradient
spoGC = spo.minimize(fnGASGaussianCopulaLikelihood, np.array([0.005,-5,5.0]),
args = (int(mData.shape[0]), mData[:, [0, 1]]),
method = 'BFGS', options = {'disp': True, 'gtol': 1e-10, 'eps': 1e-10})
I get:
Optimization terminated successfully.
Current function value: nan
Iterations: 0
Function evaluations: 5
Gradient evaluations: 1
Out[34]:
(array([ 0.005 , 1.0067607 , 0.72974065]),
nan,
array([ nan, nan, nan]),
array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]),
5,
1,
0)
which is clearly no good. I am unable to figure out what is causing this issue. Any help would be appreciated.
Related
I have a linear problem to solve looking for integer numbers. I found a way to solve it using the new milp implementation in spicy. Hereafter is a demonstration code.
The problem is the following. From a vector of weights w I am looking for the integer vector x such as the dot product of x and weights is in a given range. It looks like something like this
# minimize
abs(w^T # x - target)
And I translated this in the following to implement in milp:
# maximize
w^T # x
# constraints
target - error <= w^T # x <= target + error
In my specific context, several solutions may exist for x. Is there a way to get all the solutions in the given interval instead of maximizing (or minimizing) something ?
Here is the milp implementation.
import numpy as np
from scipy.optimize import milp, LinearConstraint, Bounds
# inputs
ratio_l, ratio_u = 0.2, 3.0
max_bounds = [100, 200, 2, 20, 2]
target = 380.2772 # 338.34175
lambda_parameter = 2
error = lambda_parameter * 1e-6 * target
# coefficients of the linear objective function
w = np.array([12.0, 1.007825, 14.003074, 15.994915, 22.989769], dtype=np.float64)
# the aim is to minimize
# w^T x - target_mass
# instead I maximize
# w^T x
# in the constraint domain
# target - error <= w^T x <= target + error
# constraints on variables 0 and 1:
# ratio_l <= x[1] / x[0] <= ratio_u
# translation =>
# (ratio_l - ratio_u) * x[1] <= -ratio_u * x[0] + x[1] <= 0
# use max (x[1]) to have a constant
# linear objective function
c = w
# integrality of the decision variables
# 3 is semi-integer = within bounds or 0
integrality = 3 * np.ones_like(w)
# Matrice A that define the constraints
A = np.array([
# boundaries of the mass defined from lambda_parameters
w,
# c[1] / c[0] max value
[-ratio_u, 1.0, 0., 0., 0.],
])
# b_up and b_low vectors
# b_low <= A # x <= b_up
n_max_C = max_bounds[0]
b_up = [
target + error, # mass target
0., # c[1] / c[0] constraints up
]
b_low = [
target - error, # mass target
(ratio_l - ratio_u) * max_bounds[0], # H_C constraints up
]
# set up linear constraints
constraints = LinearConstraint(A, b_low, b_up)
bounds = Bounds(
lb=[0, 0, 0, 0, 0],
ub=max_bounds,
)
results = milp(
c=c,
constraints=constraints,
integrality=integrality,
bounds=bounds,
options=dict(),
)
print(results)
The results is this
fun: 380.277405
message: 'Optimization terminated successfully. (HiGHS Status 7: Optimal)'
mip_dual_bound: 380.27643944560145
mip_gap: 2.5390790665913637e-06
mip_node_count: 55
status: 0
success: True
x: array([19., 40., 0., 7., 0.])
But it exists other possible x arrays but with an highest error. This one is the
m = np.dot(w, [19., 40., 0., 7., 0.])
print(f"{'target':>10s} {'calc m':>27s} {'deviation':>27s} {'error':>12s} match?")
print(f"{target:10.6f} {target - error:14.6f} <= {m:10.6f} <= {target + error:10.6f}"
f" {m - target:12.6f} {error:12.6f} -> {target - error <= m <= target + error}")
target calc m deviation error match?
380.277200 380.276439 <= 380.277405 <= 380.277961 0.000205 0.000761 -> True
These two other examples work also and I wonder how I can got them without implementing a grid algorithm (like brute in scipy).
m = np.dot(w, [20., 39., 1., 4., 1.])
print(f"{'target':>10s} {'calc m':>27s} {'deviation':>27s} {'error':>12s} match?")
print(f"{target:10.6f} {target - error:14.6f} <= {m:10.6f} <= {target + error:10.6f}"
f" {m - target:12.6f} {error:12.6f} -> {target - error <= m <= target + error}")
target calc m deviation error match?
380.277200 380.276439 <= 380.277678 <= 380.277961 0.000478 0.000761 -> True
m = np.dot(w, [21., 38., 2., 1., 2.])
print(f"{'target':>10s} {'calc m':>27s} {'deviation':>27s} {'error':>12s} match?")
print(f"{target:10.6f} {target - error:14.6f} <= {m:10.6f} <= {target + error:10.6f}"
f" {m - target:12.6f} {error:12.6f} -> {target - error <= m <= target + error}")
target calc m deviation error match?
380.277200 380.276439 <= 380.277951 <= 380.277961 0.000751 0.000761 -> True
Linear programming is for optimization, which is generally to pick the single best solution in a solution space. Your problem cannot pick a single solution. Since you have well-bounded integral variables, "brute force" (though not iterative brute force) is quite practical. This looks like:
Within the known bounds of x, attempt all values for all dimensions excluding the largest one (x1, which can range between 0 and 200)
Calculate bounds arrays based on your "ratio" constraint
Calculate bounds arrays based on the "error from target" constraint
Combine the two to find overall bounds
Filter on integral solutions that are within the bounds
import numpy as np
ratio_l, ratio_u = 0.2, 3.0
max_bounds = (100, 200, 2, 20, 2)
target = 380.2772
lambda_parameter = 2
error = 1e-6 * lambda_parameter * target
w = np.array((12.0, 1.007825, 14.003074, 15.994915, 22.989769))
i0234 = [0, 2, 3, 4]
w0234 = w[i0234]
x0234 = np.stack(np.meshgrid(
*(np.arange(1+max_bounds[m]) for m in i0234)
)).reshape((4, -1))
x0, x2, x3, x4 = x0234
x1_ratio_lower, x1_ratio_upper = np.multiply.outer((ratio_l, ratio_u), x0)
x1_target_lower, x1_target_upper = (target - np.add.outer((error, -error), w0234#x0234))/w[1]
x1_lower = np.ceil(np.max((x1_ratio_lower, x1_target_lower), axis=0)).astype(int)
x1_upper = np.floor(np.min((x1_ratio_upper, x1_target_upper), axis=0)).astype(int)
ok, = (x1_upper >= x1_lower).nonzero()
for i in ok:
xi = x0234[:, i]
for x1 in range(x1_lower[i], x1_upper[i]+1):
x = [xi[0], x1, *xi[1:]]
target_approx = w.dot(x)
error_approx = target_approx - target
print(f'x={x} w#x={target_approx:.6f} ~ {target}, '
f'error={error_approx:.2e}<{error:.2e}')
x=[19, 40, 0, 7, 0] w#x=380.277405 ~ 380.2772, error=2.05e-04<7.61e-04
x=[20, 39, 1, 4, 1] w#x=380.277678 ~ 380.2772, error=4.78e-04<7.61e-04
x=[21, 38, 2, 1, 2] w#x=380.277951 ~ 380.2772, error=7.51e-04<7.61e-04
A simple boundary contraction reduces the search space:
import numpy as np
ratio_l, ratio_u = 0.2, 3.0
max_bounds = np.array((100, 200, 2, 20, 2))
target = 380.2772
lambda_parameter = 2
error = 1e-6 * lambda_parameter * target
w = np.array((12.0, 1.007825, 14.003074, 15.994915, 22.989769))
x0u = (target + error) / (w[0] + w[1] * ratio_l)
assert np.isclose(target, w.dot((x0u, x0u * ratio_l, 0, 0, 0)) - error)
max_bounds[0] = min(max_bounds[0], np.floor(x0u))
i0234 = [0, 2, 3, 4]
w0234 = w[i0234]
x0234 = np.stack(np.meshgrid(
*(np.arange(1+max_bounds[m]) for m in i0234)
)).reshape((4, -1))
x0, x2, x3, x4 = x0234
x1_ratio_lower, x1_ratio_upper = np.multiply.outer((ratio_l, ratio_u), x0)
x1_target_lower, x1_target_upper = (target - np.add.outer((error, -error), w0234#x0234))/w[1]
x1_lower = np.ceil(np.max((x1_ratio_lower, x1_target_lower), axis=0)).astype(int)
x1_upper = np.floor(np.min((x1_ratio_upper, x1_target_upper), axis=0)).astype(int)
ok, = (x1_upper >= x1_lower).nonzero()
for i in ok:
xi = x0234[:, i]
for x1 in range(x1_lower[i], x1_upper[i]+1):
x = [xi[0], x1, *xi[1:]]
target_approx = w.dot(x)
error_approx = target_approx - target
print(f'x={x} w#x={target_approx:.6f} ~ {target}, '
f'error={error_approx:.2e}<{error:.2e}')
I have tried to use a toy problem of linear regression for implanting the optimisation on the MSE function using the algorithm of gradient decent.
import numpy as np
# Data points
x = np.array([1, 2, 3, 4])
y = np.array([1, 1, 2, 2])
# MSE function
f = lambda a, b: 1 / len(x) * np.sum(np.power(y - (a * x + b), 2))
# Gradient
def grad_f(v_coefficients):
a = v_coefficients[0, 0]
b = v_coefficients[1, 0]
return np.array([1 / len(x) * np.sum(2 * (y - (a * x + b)) * x),
1 / len(x) * np.sum(2 * (y - (a * x + b)))]).reshape(2, 1)
# Gradient Decent with epsilon as tol vector and alpha as the step/learning rate
def gradient_decent(v_prev):
tol = 10 ** -3
epsilon = np.array([tol * np.ones([2, 1], int)])
alpha = 0.2
v_next = v_prev - alpha * grad_f(v_prev)
if (np.abs(v_next - v_prev) <= epsilon).all():
return v_next
else:
gradient_decent(v_next)
# v_0 is the initial guess
v_0 = np.array([[1], [1]])
gradient_decent(v_0)
I have tried different alpha values but the code never converges (infinite recursion) it seems that the issue is with the stop condition of the recursion, but after few runs the v_next and v_prev bounces between -infinte to infinite
It's great that you are learning machine learning (^_^) by implementing some base algorithms by yourself. Regarding your question, there are two problems in your code, first one is mathematical, the sign in:
def grad_f(v_coefficients):
a = v_coefficients[0, 0]
b = v_coefficients[1, 0]
return np.array([1 / len(x) * np.sum(2 * (y - (a * x + b)) * x),
1 / len(x) * np.sum(2 * (y - (a * x + b)))]).reshape(2, 1)
should be
return -np.array(...)
since
the second one is programming, this kind of code will not return you a result in Python:
def add(x):
new_x = x + 1
if new_x > 10:
return new_x
else:
add(new_x)
you must use return in both clauses of the if statement, so it should be
def add(x):
new_x = x + 1
if new_x > 10:
return new_x
else:
return add(new_x)
There is also a minor issue with the alpha coefficient for these particular data points alpha=0.2 is too big for algorithm to converge, you need to use smaller alpha. I also slightly refactor your initial code using numpy broadcasting convention (https://numpy.org/doc/stable/user/basics.broadcasting.html) to get the following result:
import numpy as np
# Data points
x = np.array([1, 2, 3, 4])
y = np.array([1, 1, 2, 2])
# MSE function
f = lambda a, b: np.mean(np.power(y - (a * x + b), 2))
# Gradient
def grad_f(v_coefficients):
a = v_coefficients[0, 0]
b = v_coefficients[1, 0]
return -np.array([np.mean(2 * (y - (a * x + b)) * x),
np.mean(2 * (y - (a * x + b)))]).reshape(2, 1)
# Gradient Decent with epsilon as tol vector and alpha as the step/learning rate
def gradient_decent(v_prev):
tol = 1e-3
# epsilon = np.array([tol * np.ones([2, 1], int)]) do not need this, due to numpy broadcasting rules
alpha = 0.1
v_next = v_prev - alpha * grad_f(v_prev)
if (np.abs(v_next - v_prev) <= alpha).all():
return v_next
else:
return gradient_decent(v_next)
# v_0 is the initial guess
v_0 = np.array([[1], [1]])
gradient_decent(v_0)
I am using sympy 1.4 to do kinematics and dynamics of ur5 robot. The express function in sympy seems to return wrong answer.ere The overall aim would be to obtain the Mass, Coriolis, Centripetal and gravity matrices as symbolic expressions. In the attached code, I am trying out a 3R manipulator
In the attached code, I am expecting the position vector of J3 frame to be 0.707106781186548*Base.i + 2.70710678118655*Base.j with respect to B where as the expression returned by the express function has a negative j.
Any idea where I am making the mistake. Or is there a better way to convert Denavit-Hartenberg representation to get the coordinate frames of the joints?
edit 1: I find that the sign convention used in sympy is just the opposite of what I have learned. For example, for a z axis rotation, the rotation matrix of B with respect to A is defined in sympy as
[cos(a) sin(a) 0;
-sin(a) cos(a) 0;
0 0 1]
Is there a way to go to the sign convention where R_z =
[cos(a) -sin(a) 0;
sin(a) cos(a) 0;
0 0 1]
without using the transpose function always?
from sympy import *
from sympy.physics.mechanics import *
from sympy.physics.vector import ReferenceFrame, Vector
from sympy.physics.vector import time_derivative
from sympy.tensor.array import Array
# Planar 3R manipulator (minimal code)
# DH representation
a = Array([0, 1, 2])
d = Array([0.0, 0.0, 0.0])
alpha = Array([0.0, 0.0, 0.0])
# q1, q2, q3 = dynamicsymbols('q1:4')
# q = [q1, q2, q3]
q = [np.pi/4, np.pi/4, 0.0,]
x_p = a[1]*cos(q[0]) + a[2]*cos(q[0] + q[1])
y_p = a[1]*sin(q[0]) + a[2]*sin(q[0] + q[1])
print 'x_p, y_p:', x_p, y_p
def transformationMatrix():
q_i = Symbol("q_i")
alpha_i = Symbol("alpha_i")
a_i = Symbol("a_i")
d_i = Symbol("d_i")
T = Matrix([[cos(q_i), -sin(q_i), 0, a_i],
[sin(q_i) * cos(alpha_i), cos(q_i) * cos(alpha_i), -sin(alpha_i), -sin(alpha_i) * d_i],
[sin(q_i) * sin(alpha_i), cos(q_i) * sin(alpha_i), cos(alpha_i), cos(alpha_i) * d_i],
[0, 0, 0, 1]])
return T
T = transformationMatrix()
q_i = Symbol("q_i")
alpha_i = Symbol("alpha_i")
a_i = Symbol("a_i")
d_i = Symbol("d_i")
T01 = T.subs(alpha_i, alpha[0]).subs(a_i, a[0]).subs(d_i, d[0]).subs(q_i, q[0])
T12 = T.subs(alpha_i, alpha[1]).subs(a_i, a[1]).subs(d_i, d[1]).subs(q_i, q[1])
T23 = T.subs(alpha_i, alpha[2]).subs(a_i, a[2]).subs(d_i, d[2]).subs(q_i, q[2])
T02 = T01*T12
T03 = T02*T23
B = CoordSys3D('Base') # Base (0) reference frame
J1 = CoordSys3D('Joint1', location=T01[0, 3]*B.i + T01[1, 3]*B.j + T01[2, 3]*B.k, rotation_matrix=T01[0:3, 0:3], parent=B)
J2 = CoordSys3D('Joint2', location=T12[0, 3]*J1.i + T12[1, 3]*J1.j + T12[2, 3]*J1.k, rotation_matrix=T12[0:3, 0:3], parent=J1)
J3 = CoordSys3D('Joint3', location=T23[0, 3]*J2.i + T23[1, 3]*J2.j + T23[2, 3]*J2.k, rotation_matrix=T23[0:3, 0:3], parent=J2)
express(J3.position_wrt(B), B)
expected result : produces 0.707106781186548*Base.i + 2.70710678118655*Base.j
actual result: produces 0.707106781186548*Base.i + (-2.70710678118655)*Base.j
given several vectors:
x1 = [3 4 6]
x2 = [2 8 1]
x3 = [5 5 4]
x4 = [6 2 1]
I wanna find weight w1, w2, w3 to each item, and get the weighted sum of each vector: yi = w1*i1 + w2*i2 + w3*i3. for example, y1 = 3*w1 + 4*w2 + 6*w3
to make the variance of these values(y1, y2, y3, y4) to be minimized.
notice: w1, w2, w3 should > 0, and w1 + w2 + w3 = 1
I don't know what kind of problems it should be... and how to solve it in python or matlab?
You can start with building a loss function stating the variance and the constraints on w's. The mean is m = (1/4)*(y1 + y2 + y3 + y4). The variance is then (1/4)*((y1-m)^2 + (y2-m)^2 + (y3-m)^2 + (y4-m)^2) and the constraint is a*(w1+w2+w3 - 1) where a is the Lagrange multiplier. The problem looks like to me a convex optimisation with convex constraints since the loss function is quadratic with respect to target variables (w1,w2,w3) and the constraints are linear. You can look for projected gradient descent algorithms which respect to the constraints provided. Take a look to here http://www.ifp.illinois.edu/~angelia/L5_exist_optimality.pdf There are no straightforward analytic solutions to such kind of problems in general.
w = [5, 6, 7]
x1 = [3, 4, 6]
x2 = [2, 8, 1]
x3 = [5, 5, 4]
y1, y2, y3 = 0, 0, 0
for index, i in enumerate(w):
y1 = y1 + i * x1[index]
y2 = y2 + i * x2[index]
y3 = y3 + i * x3[index]
print(min(y1, y2, y3))
I think I maybe get the purpose of your problem.But if you want to find the smallest value, I hope this can help you.
I just make the values fixed, you can make it to be the def when you see this is one way to solve your question.
I don't know much about optimization problem, but I get the idea of gradient descent so I tried to reduce the weight between the max score and min score, my script is below:
# coding: utf-8
import numpy as np
#7.72
#7.6
#8.26
def get_max(alist):
max_score = max(alist)
idx = alist.index(max_score)
return max_score, idx
def get_min(alist):
max_score = min(alist)
idx = alist.index(max_score)
return max_score, idx
def get_weighted(alist,aweight):
res = []
for i in range(0, len(alist)):
res.append(alist[i]*aweight[i])
return res
def get_sub(list1, list2):
res = []
for i in range(0, len(list1)):
res.append(list1[i] - list2[i])
return res
def grad_dec(w,dist, st = 0.001):
max_item, max_item_idx = get_max(dist)
min_item, min_item_idx = get_min(dist)
w[max_item_idx] = w[max_item_idx] - st
w[min_item_idx] = w[min_item_idx] + st
def cal_score(w, x):
score = []
print 'weight', w ,x
for i in range(0, len(x)):
score_i = 0
for j in range(0,5):
score_i = w[j]*x[i][j] + score_i
score.append(score_i)
# check variance is small enough
print 'score', score
return score
# cal_score(w,x)
if __name__ == "__main__":
init_w = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
x = [[7.3, 10, 8.3, 8.8, 4.2], [6.8, 8.9, 8.4, 9.7, 4.2], [6.9, 9.9, 9.7, 8.1, 6.7]]
score = cal_score(init_w,x)
variance = np.var(score)
round = 0
for round in range(0, 100):
if variance < 0.012:
print 'ok'
break
max_score, idx = get_max(score)
min_score, idx2 = get_min(score)
weighted_1 = get_weighted(x[idx], init_w)
weighted_2 = get_weighted(x[idx2], init_w)
dist = get_sub(weighted_1, weighted_2)
# print max_score, idx, min_score, idx2, dist
grad_dec(init_w, dist)
score = cal_score(init_w, x)
variance = np.var(score)
print 'variance', variance
print score
In my practice it really can reduce the variance. I am very glad but I don't know whether my solution is solid in math.
My full solution can be viewed in PDF.
The trick is to put the vectors x_i as columns of a matrix X.
Then writing the problem becomes a Convex Problem with constrain of the solution to be on the Unit Simplex.
I solved it using Projected Sub Gradient Method.
I calculated the Gradient of the objective function and created a projection to the Unit Simplex.
Now all needed is to iterate them.
I validated my solution using CVX.
% StackOverflow 44984132
% How to calculate weight to minimize variance?
% Remarks:
% 1. sa
% TODO:
% 1. ds
% Release Notes
% - 1.0.000 08/07/2017
% * First release.
%% General Parameters
run('InitScript.m');
figureIdx = 0; %<! Continue from Question 1
figureCounterSpec = '%04d';
generateFigures = OFF;
%% Simulation Parameters
dimOrder = 3;
numSamples = 4;
mX = randi([1, 10], [dimOrder, numSamples]);
vE = ones([dimOrder, 1]);
%% Solve Using CVX
cvx_begin('quiet')
cvx_precision('best');
variable vW(numSamples)
minimize( (0.5 * sum_square_abs( mX * vW - (1 / numSamples) * (vE.' * mX * vW) * vE )) )
subject to
sum(vW) == 1;
vW >= 0;
cvx_end
disp([' ']);
disp(['CVX Solution - [ ', num2str(vW.'), ' ]']);
%% Solve Using Projected Sub Gradient
numIterations = 20000;
stepSize = 0.001;
simplexRadius = 1; %<! Unit Simplex Radius
stopThr = 1e-6;
hKernelFun = #(vW) ((mX * vW) - ((1 / numSamples) * ((vE.' * mX * vW) * vE)));
hObjFun = #(vW) 0.5 * sum(hKernelFun(vW) .^ 2);
hGradFun = #(vW) (mX.' * hKernelFun(vW)) - ((1 / numSamples) * vE.' * (hKernelFun(vW)) * mX.' * vE);
vW = rand([numSamples, 1]);
vW = vW(:) / sum(vW);
for ii = 1:numIterations
vGradW = hGradFun(vW);
vW = vW - (stepSize * vGradW);
% Projecting onto the Unit Simplex
% sum(vW) == 1, vW >= 0.
vW = ProjectSimplex(vW, simplexRadius, stopThr);
end
disp([' ']);
disp(['Projected Sub Gradient Solution - [ ', num2str(vW.'), ' ]']);
%% Restore Defaults
% set(0, 'DefaultFigureWindowStyle', 'normal');
% set(0, 'DefaultAxesLooseInset', defaultLoosInset);
You can see the full code in StackOverflow Q44984132 (PDF is available as well).
I'm trying to maximize/minimize a function with two variables using Lagrange Multiplier method, below is my code
import numpy as np
from scipy.optimize import fsolve
Sa = 200
Sm = 100
n = 90
mu1 = 500
mu2 = 150
sigma1 = 25
sigma2 = 10
f = 0.9
def func(X):
u1 = X[0]
u2 = X[1]
L = X[2] # this is the multiplier. lambda is a reserved keyword in python
'function --> f(u1,u2) = u1**2 + u2**2'
'constraint --> g(u1,u2) = (Snf/a)**1/b - n = 0'
Snf = Sa/(1-Sm/(sigma1*u1 + mu1))
a = (f*(sigma1*u1 + mu1)**2)/(sigma2*u2 + mu2)
b = -1/3*(f*(sigma1*u1 + mu1))/(sigma2*u2 + mu2)
return (u1**2+u2**2 - L * ((Snf/a)**1/b) - n)
def dfunc(X):
dLambda = np.zeros(len(X))
h = 1e-3 # this is the step size used in the finite difference.
for i in range(len(X)):
dX = np.zeros(len(X))
dX[i] = h
dLambda[i] = (func(X+dX)-func(X-dX))/(2*h);
return dLambda
# this is the max
X1 = fsolve(dfunc, [1, 1, 0])
print (X1, func(X1))
# this is the min
X2 = fsolve(dfunc, [-1, -1, 0])
print (X2, func(X2))
When I try to do a simple function as the constraint such as u1+u2=4 or u1^2+u2^2 = 20, it works just fine , but when I try my actual constraint function it always gives this error, is there a reason why?? THanks for the help
C:\Python34\lib\site-packages\scipy\optimize\minpack.py:161:
RuntimeWarning: The iteration is not making good progress, as measured by the
improvement from the last five Jacobian evaluations.
warnings.warn(msg, RuntimeWarning)