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.
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]
Related
I have a dictionary with a tuple as key and a result as value.
I'm looking for a way to "solve" as many keys as possible, even if it's not possible to "solve" all of then.
input : {(A, C):1,(A, B, C): 1}
output : {(A, C):1, (A, B, C): 1, B:0}
in other word :
modified input :
1*A + 0*B + 1*C = 1
1*A + 1*B + 1*C = 1
output :
A = ?
B = 0
C = ?
I can only use numpy and scipy.
I tried this, but it must be square matrix :
import numpy as np
a = np.array([[1, 0, 1], [1, 1, 1]])
b = np.array([1, 1])
from scipy import linalg
x = linalg.solve(a, b)
print(x)
Do you have ideas where I should look at ?
this code does the trick, but it's not very 'clean'
import numpy as np
A=np.array([[1, 0, 1], [1, 1, 1]])
B=np.array([1,1])
s = solutionNonSquare = np.linalg.lstsq(A, B)[0]
for i,val in enumerate(s):
if val < 0.0001:
print('x[',i,'] = 0')
else:
print('x[',i,'] = ?')
print(s)
Thanks a lot for your smartness
Matrix a is Non square Matrix, so it does not have full Rank. However, we can compute pseudo inverse, using np.linalg.pinv and then we can compute x = np.matmul(a_psudo_inv, b)
import numpy as np
a = np.array([[1, 0, 1], [1, 1, 1]])
b = np.array([1, 1])
from numpy import linalg
a_psudo_inv = np.linalg.pinv(a)
print(a_psudo_inv)
print(a_psudo_inv.shape)
x = np.matmul(a_psudo_inv, b)
print(x)
Solution >> [5.00000000e-01 5.55111512e-16 5.00000000e-01]
I have an optimization problem where I'm trying to find an array that needs to optimize two functions simultaneously.
In the minimal example below I have two known arrays w and x and an unknown array y. I initialize array y to contains only 1s.
I then specify function np.sqrt(np.sum((x-np.array)**2) and want to find the array y where
np.sqrt(np.sum((x-y)**2) approaches 5
np.sqrt(np.sum((w-y)**2) approaches 8
The code below can be used to successfully optimize y with respect to a single array, but I would like to find that the solution that optimizes y with respect to both x and y simultaneously, but am unsure how to specify the two constraints.
y should only consist of values greater than 0.
Any ideas on how to go about this ?
w = np.array([6, 3, 1, 0, 2])
x = np.array([3, 4, 5, 6, 7])
y = np.array([1, 1, 1, 1, 1])
def func(x, y):
z = np.sqrt(np.sum((x-y)**2)) - 5
return np.zeros(x.shape[0],) + z
r = opt.root(func, x0=y, method='hybr')
print(r.x)
# array([1.97522498 3.47287981 5.1943792 2.10120135 4.09593969])
print(np.sqrt(np.sum((x-r.x)**2)))
# 5.0
One option is to use scipy.optimize.minimize instead of root, Here you have multiple solver options and some of them (ie SLSQP) allow you to specify multiple constraints. Note that I changed the variable names so that x is the array you want to optimise and y and z define the constraints.
from scipy.optimize import minimize
import numpy as np
x0 = np.array([1, 1, 1, 1, 1])
y = np.array([6, 3, 1, 0, 2])
z = np.array([3, 4, 5, 6, 7])
constraint_x = dict(type='ineq',
fun=lambda x: x) # fulfilled if > 0
constraint_y = dict(type='eq',
fun=lambda x: np.linalg.norm(x-y) - 5) # fulfilled if == 0
constraint_z = dict(type='eq',
fun=lambda x: np.linalg.norm(x-z) - 8) # fulfilled if == 0
res = minimize(fun=lambda x: np.linalg.norm(x), constraints=[constraint_y, constraint_z], x0=x0,
method='SLSQP', options=dict(ftol=1e-8)) # default 1e-6
print(res.x) # [1.55517124 1.44981672 1.46921122 1.61335466 2.13174483]
print(np.linalg.norm(res.x-y)) # 5.00000000137866
print(np.linalg.norm(res.x-z)) # 8.000000000930026
This is a minimizer so besides the constraints it also wants a function to minimize, I chose just the norm of y, but setting the function to a constant (ie lambda x: 1) would have also worked.
Note also that the constraints are not exactly fulfilled, you can increase the accuracy by setting optional argument ftol to a smaller value ie 1e-10.
For more information see also the documentation and the corresponding sections for each solver.
I'm trying to solve a simple equation: dM/dr = r*p(r) in python.
I have the values of p at certain values of r:
p(0)=1, p(1)=3, p(2)=5, p(3)=7, p(4)=9, p(5)=11.
I tried using the following code but I get the error
The size of the array returned by func (6) does not match the size of
y0 (1).
I think the problem is that I'm not matching the p values with the r values correctly. There should only be one initial condition since I am only trying to solve one equation. Any help would be greatly appreciated.
This is my code:
from scipy import integrate
import numpy as np
r = np.array([0, 1, 2, 3, 4, 5])
p = np.array([1, 3, 5, 7, 9, 11])
def deriv (z, r, data):
M = r*p
return M
init = np.array([0])
soln = integrate.odeint(deriv, init, p, (r,), full_output=True)
print soln
You are seeing this error because the size of init does not match the size of the array returned by deriv().
To solve the problem, change the following line
init = np.array([0])
to
init = np.array([0, 0, 0, 0, 0, 0])
For more examples on using 'odeint', see:
http://scipy-cookbook.readthedocs.org/items/numpy_scipy_ordinary_differential_equations.html
http://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html
In mathematics, a "generating function" is defined from a sequence of numbers c0, c1, c2, ..., cn by c0+c1*x+c2*x^2 + ... + cn*x^n. These come as "moment generating functions", "probability generating functions" and various other types, depending on the source of the coefficient.
I have an array of the coefficients and I'd like a quick way to create the corresponding generating function.
I could do
import numpy as np
myArray = np.array([1,2,3,4])
x=0.2
sum([c*x**k for k,c in enumerate myArray])
or I could have an array having c[k] in the kth entry. It seems there should be a fast numpy way to do this.
Unfortunately attempts to look this up are complicated by the fact that "generate" and "function" are common words in programming, as is the combination "generating function" so I haven't had any luck with search engines.
x = .2
coeffs = np.array([1,2,3,4])
Make an array of the degree of each term
degrees = np.arange(len(coeffs))
Raise x the each degree
terms = np.power(x, degrees)
Multiply the coefficients and sum
result = np.sum(coeffs*terms)
>>> coeffs
array([1, 2, 3, 4])
>>> degrees
array([0, 1, 2, 3])
>>> terms
array([ 1. , 0.2 , 0.04 , 0.008])
>>> result
1.552
>>>
As a function:
def f(coeffs, x):
degrees = np.arange(len(coeffs))
terms = np.power(x, degrees)
return np.sum(coeffs*terms)
Or simply us the Numpy Polynomial Package
from numpy.polynomial import Polynomial as P
p = P(coeffs)
result = p(x)
If you are looking for performance, using np.einsum could be suggested too -
np.einsum('i,i->',myArray,x**np.arange(myArray.size))
>>> coeffs = np.random.random(5)
>>> coeffs
array([ 0.70632473, 0.75266724, 0.70575037, 0.49293719, 0.66905641])
>>> x = np.random.random()
>>> x
0.7252944971757169
>>> powers = np.arange(0, coeffs.shape[0], 1)
>>> powers
array([0, 1, 2, 3, 4])
>>> result = coeffs * x ** powers
>>> result
array([ 0.70632473, 0.54590541, 0.37126147, 0.18807659, 0.18514853])
>>> np.sum(result)
1.9967167252487628
Using numpys Polynomial class is probably the easiest way.
from numpy.polynomial import Polynomial
coefficients = [1,2,3,4]
f = Polynomial( coefficients )
You can then use the object like any other function.
import numpy as np
import matplotlib.pyplot as plt
print f( 0.2 )
x = np.linspace( -5, 5, 51 )
plt.plot( x , f(x) )
I am converting this matlab function handle to python and am receiving this error (ValueError: setting an array element with a sequence.) in python. I'm pretty new to python sorry if there is an obvious error.
In matlab:
P = [1 1; 6 1; 6 5]
fh = #(x) sqrt(sum((ones(3,1)*x - P).^2, 2))
[x,fval] = fminsearch(#(x) max(fh(x)),[0 0])
In python:
P = np.matrix([[1, 1],[ 6, 1],[ 6, 5]])
fh = lambda x:np.sqrt(sum(np.power((np.ones((3,1))*x - P),2),axis = 0))
xopt = scipy.optimize.fmin(func=fh,x0 = np.matrix([0, 0]))
The code works in matlab but not in python thanks.
In your matlab code, fminsearch is minimizing the max of fh(x). In the Python code, therefore, the func passed to fmin should be the max of fh as well:
import numpy as np
from scipy import optimize
P = np.array([[1, 1],[ 6, 1],[ 6, 5]])
def fh(x):
return np.max(np.sqrt(np.sum((x - P)**2, axis=1)))
xopt = optimize.fmin(func=fh, x0=np.array([0, 0]))
print(xopt)
yields
Optimization terminated successfully.
Current function value: 3.201562
Iterations: 117
Function evaluations: 222
[ 3.50007127 2.99991092]