4

I am trying to implement the same Sage code here: find vector center in python, as follows:

import numpy as np
from scipy.optimize import minimize
def norm(x):
    return x/np.linalg.norm(x)

vectors = np.array([[1,2,3],[4,5,6],[7,8,9]])
unit_vectors = [np.divide(v,norm(v)) for v in vectors]
constraints = [lambda x: np.dot(x,u)-1 for u in unit_vectors]
target = lambda x: norm(x)
res = minimize(target,[3,3,3],constraints)

But I keep getting the same problem:

TypeError: <lambda>() takes 1 positional argument but 2 were given

I am not a mathematician, I just want to write a code that can find a center of multidimensional vectors. I tried many things to solve the problem but nothing worked.

Thanks.

Sarah N
  • 43
  • 1
  • 4
  • 1
    Unrelated, `lambda x: np.dot(x,u) - 1` doesn't do what you are expecting. `u` is a free variable looked up when the function is called, not the value `u` had when the function was defined. – chepner Jan 03 '20 at 20:42
  • 1
    One thing that is extremely helpful in situations like this is to pass arguments into the function by name, rather than positionally. As in your edit, it's not clear which argument in `minimize` is meant to be what. At the moment the inference seems to be that you're calling `minimize(fun=target, x0=[3,3,3], args=constraints)` which may or may not be what's intended – G. Anderson Jan 03 '20 at 20:43
  • Note, do not assign lambdas to a name, that defeats their entire purpose and is against PEP8 style guidelines. I.e. don't do: `target = lambda x: norm(x)`. Note, this is sort of pointless anyway, you could just use `norm`, the lambda serves no purpose. Even if you simply want d a different name, you could use `target = norm` – juanpa.arrivillaga Jan 03 '20 at 21:18

1 Answers1

5

The algorithm of the answer that you indicate is not written in python, so which obviously can fail, considering the official docs I have implemented the following solution:

import numpy as np
from scipy.optimize import minimize


x0 = 10, 10, 10

vectors = [
    np.array([1, 2, 3]),
    np.array([1, 0, 2]),
    np.array([3, 2, 4]),
    np.array([5, 2, -1]),
    np.array([1, 1, -1]),
]

unit_vectors = [vector / np.linalg.norm(vector) for vector in vectors]
constraints = [
    {"type": "ineq", "fun": lambda x, u=u: (np.dot(x, u) - 1)} for u in unit_vectors
]

target = lambda x: np.linalg.norm(x)
res = minimize(fun=target, x0=x0, constraints=constraints)
print(res.x)

Output:

[1.38118173 0.77831221 0.42744313]
eyllanesc
  • 235,170
  • 19
  • 170
  • 241