3

I'm trying to minimize a function that has arguments S1, S2, S3 and n1, n2, and n3. There are also weights: w1, w2, and w3.

This is the function:

f = (w1**2 * n1**2 + w2**2 * n2**2 + w3**2 * n3**2) / (w1**2 * S1**2 + w2**2 * S2**2 + w3**2 * S3**2 + 2*w1*S1*w2*S2 * 2*w1*S1*w2*S2 + 2*w2*S2*w3*S3)

I want to know given S1, S2, S3, n1, n2, and n3, what w1, w2, and w3 will minimize f?

Here's my code so far:

def opt(S1, S2, S3, n1, n2, n3):
    xo = np.array([0,1,.01])
    from scipy.optimize import minimize
    signoise = lambda w1,w2,w3: (w1**2 * n1**2 + w2**2 * n2**2 + w3**2 * n3**2) / (w1**2 * S1**2 + w2**2 * S2**2 + w3**2 * S3**2 + 2*w1*S1*w2*S2 * 2*w1*S1*w2*S2 + 2*w2*S2*w3*S3)
    w1min, w2min, w3min = scipy.optimize.minimize(signoise, (.4, .2, .4))
    return w1min, w2min, w3min

scipy.optimize.minimize takes two arguments, the function and an initial guess. I don't know if it works for multivariable functions, because I'm getting the

error : <lambda>() takes exactly 3 arguments (1 given)

Okay, I followed CodyKramer's suggestion. When I tested it with arbitrary values for S1, S2, S3, n1, n2, n3, I got all of this as an answer : status: 0 success: True njev: 1 nfev: 5 hess_inv: array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) fun: 5.1874999894628917e-18 x: array([ 0.4, 0.2, 0.4]) message: 'Optimization terminated successfully.' jac: array([ -1.81249989e-17, -4.62499946e-17, 1.53125002e-17]) Is that last line the 'jac' the three numbers I was looking for?

hazel
  • 31
  • 1
  • 1
  • 3
  • The answer is the array `x` in your output. `jac` is the [Jacobian matrix](https://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant) which is the (basically) first derivative of `x`, and `hess` is the [Hessian matrix](https://en.wikipedia.org/wiki/Hessian_matrix) which is (basically) the second derivative of `x` – Cory Kramer Jul 25 '15 at 13:42

1 Answers1

3

The problem is that as written your lambda takes 3 arguments, not 1 argument (that happens to be a sequence with 3 elements). I would pull out your objective function into a standalone function

def signoise(w):
    w1, w2, w3 = w  # unpack your tuple into each variable
    # populate your S and n coefficients
    return w1**2 * n1**2 + w2**2 * n2**2 + w3**2 * n3**2) / (w1**2 * S1**2 + w2**2 * S2**2 + w3**2 * S3**2 + 2*w1*S1*w2*S2 * 2*w1*S1*w2*S2 + 2*w2*S2*w3*S3

Then you can modify your function to

def opt(S1, S2, S3, n1, n2, n3):
    xo = np.array([0,1,.01])
    from scipy.optimize import minimize
    return scipy.optimize.minimize(signoise, (.4, .2, .4))
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • Okay, I followed your suggestion. When I tested it with arbitrary values for S1, S2, S3, n1, n2, n3, I got all of this as an answer : status: 0 success: True njev: 1 nfev: 5 hess_inv: array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) fun: 5.1874999894628917e-18 x: array([ 0.4, 0.2, 0.4]) message: 'Optimization terminated successfully.' jac: array([ -1.81249989e-17, -4.62499946e-17, 1.53125002e-17]) Is that last line the 'jac' the three numbers I was looking for? – hazel Jul 16 '15 at 20:38
  • Can you please edit your question to include that? Unfortunately all formatting is lost in the comment section so it's hard to parse that output visually – Cory Kramer Jul 16 '15 at 21:23