linear algebra (partial) solving in python - python

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]

Related

Factoring a polynomial with respect to specific terms

import numpy as np
import sympy as sp
from sympy import *
init_printing()
uVars = list(symbols(', '.join([f'u{n}' for n in range(1, 3 + 1)])))
aVars = list(symbols(', '.join([f'a{n}' for n in range(1, 3 + 1)])))
lambda1, mu = symbols('lambda, mu')
U = np.array([ [0, -uVars[2], uVars[1]], [uVars[2], 0, -uVars[0]], [-uVars[1], uVars[0], 0] ])
a = np.array([ [aVars[0], 0, 0], [0, aVars[1], 0], [0, 0, aVars[2]] ])
I = np.eye(3)
L = a*lambda1 + U
preCharPoly = L - mu*I
preCharPoly_sym = sp.Matrix(preCharPoly)
factor(preCharPoly_sym.det())
The above code outputs the following polynomial:
However, I require the polynomial to be factored with respect to the variables lambda and mu as shown here:
I have been examining the documentation at https://docs.sympy.org/latest/modules/simplify/simplify.html but cannot figure out how to do what is desired. How do I specify factor() or simplify() to perform their tasks with respect to lambda and mu?

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

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]

given permuted arrays, find permutation

I have two numpy integer arrays,
import numpy
a = numpy.array([1, 3, 5, 0])
b = numpy.array([3, 5, 0, 1])
which I know are permutations of each other. How can I find the permutation, i.e., the integer array i such that
a[i] == b
? Explicit for loops with comparisons across the entire arrays works, but seems inefficient.
Bonus points if it works of permutation of row-arrays like
import numpy
a = numpy.array([
[1, 2],
[3, 7],
[5, 12],
[0, 4],
# ...
])
b = numpy.array([
[3, 7],
[5, 12],
[0, 4],
[1, 2],
# ...
])
Here's one using argsort twice. It seems a few percent faster than #Divakar's:
from simple_benchmark import BenchmarkBuilder, MultiArgument
import numpy as np
B = BenchmarkBuilder()
#B.add_function()
def div(A,B):
sidx = A.argsort()
return sidx[np.searchsorted(A,B,sorter=sidx)]
#B.add_function()
def pp(A,B):
oa,ob = (x.argsort() for x in (A,B))
o = np.empty_like(oa)
o[ob] = oa
return o
#B.add_arguments('array size')
def argument_provider():
for exp in range(8, 30):
dim_size = int(1.4**exp)
a = np.random.permutation(dim_size)
b = np.random.permutation(dim_size)
yield dim_size, MultiArgument([a,b])
r = B.run()
r.plot()
import pylab
pylab.savefig('bm.png')
Here's one with np.searchsorted on 1D-views for 2D arrays -
# https://stackoverflow.com/a/45313353/ #Divakar
def view1D(a, b): # a, b are arrays
a = np.ascontiguousarray(a)
b = np.ascontiguousarray(b)
void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
return a.view(void_dt).ravel(), b.view(void_dt).ravel()
A,B = view1D(a,b)
sidx = A.argsort()
idx = sidx[np.searchsorted(A,B,sorter=sidx)]
For 1D input arrays, we can directly feed in a and b as A and B respectively.
Alternatively, for positive integers, we can use dimensionality-reduction with grid-mapping, keeping rest of it same as earlier -
s = np.r_[1,a[:,:-1].max(0)+1]
A,B = a.dot(s),b.dot(s)
Or use np.ravel_multi_index to do the mapping on 2D-grid -
shp = a.max(0)+1
A,B = np.ravel_multi_index(a.T,shp),np.ravel_multi_index(b.T,shp)
Another for positive integers with sparse-matrix using the same grid-mapping technique -
from scipy.sparse import csr_matrix
R = np.arange(1,len(a)+1)
c = csr_matrix((R, a.T), shape=a.max(0)+1)
idx = c[b[:,0],b[:,1]].A1-1

Python linprog minimization--simplex method

I'm using scipy.optimize.linprog library to calculate the minimization using the simplex method. I'm working on this problem in my textbook and I'm hoping someone can point me in the right direction because I'm not getting the output I expect. The problem is:
Minimize w = 10*y1 + 15*y2 + 25*y3
Subject to: y1 + y2 + y3 >= 1000
y1 - 2*y2 >= 0
y3 >= 340
with y1 >= 0, y2 >= 0
The code I wrote for this is:
import numpy as np
import pandas as pd
from scipy.optimize import linprog
A = np.array([
[1, 1, 1],
[1,-2, 0],
[0, 0, 1]])
b = np.array([1000,0,340])
c = np.array([-10,-15,-25])
res = linprog(c, A_ub=A, b_ub=b,
bounds=(0, None))
print('Optimal value:', res.fun, '\nX:', res.x)
Which gives the output:
Optimal value: -18400.0
X: [ 0. 660. 340.]
I expect it to be:
Optimal value: -15100.0
X: [ 660. 0. 340.]
I can't seem to find consistency with this function but maybe it's the way I'm using it.
You've set up the inputs slightly wrong; see the manual. Specifically, you have a number of sign errors.
Your vector c has the wrong sign; linprog minimizes c x so c should just be the coefficients in w = c x
Your vector b and matrix A have the wrong sign. Their signs should be inverted to switch from your form of constraint f(x) >= const to the desired form for the linprog method, which is a less-than-or-equal, i.e. -f(x) <= - const
You are missing the final two constraints.
Your proposed minimum is < 0, which is obviously impossible as
w = 10*x1 + 15*x2 + 25*x3 is always positive with your constraints as x1,x2,x3>=0.
The correct code reads:
import numpy as np
from scipy.optimize import linprog
A = np.array([[-1, -1, -1], [-1,2, 0], [0, 0, -1], [-1, 0, 0], [0, -1, 0]])
b = np.array([-1000, 0, -340, 0, 0])
c = np.array([10,15,25])
res = linprog(c, A_ub=A, b_ub=b,bounds=(0, None))
print('Optimal value:', res.fun, '\nX:', res.x)
# python2
# ('Optimal value:', 15100.0, '\nX:', array([ 660., 0., 340.]))
# python3
# Optimal value: 15099.999961403426
# X: [6.59999996e+02 1.00009440e-07 3.40000000e+02]
As the positiveness of y1 and y2 can be guaranteed under bounds=(0, None), a simplified version of code is shown as below:
import numpy as np
from scipy.optimize import linprog
A = np.array([[-1, -1, -1], [-1,2, 0], [0, 0, -1]])
b = np.array([-1000, 0, -340])
c = np.array([10,15,25])
res = linprog(c, A_ub=A, b_ub=b,bounds=(0, None))
print('Optimal value:', res.fun, '\nX:', res.x)
Output:
Optimal value: 15099.999961403195
X: [6.59999996e+02 1.00009440e-07 3.40000000e+02]

Weighted sum of adjacent values in numpy array

What is the easiest/fastest way to take a weighted sum of values in a numpy array?
Example: Solving the heat equation with the Euler method
length_l=10
time_l=10
u=zeros((length_l,length_l))# (x,y)
u[:, 0]=1
u[:,-1]=1
print(u)
def dStep(ALPHA=0.1):
for position,value in ndenumerate(u):
D2u= (u[position+(1,0)]-2*value+u[position+(-1, 0)])/(1**2) \
+(u[position+(0,1)]-2*value+u[position+( 0,-1)])/(1**2)
value+=ALPHA*D2u()
while True:
dStep()
print(u)
D2u should be the second central difference in two dimensions. This would work if I could add indexes like (1,4)+(1,3)=(2,7). Unfortunately, python adds them as (1,4)+(1,3)=(1,4,1,3).
Note that computing D2u is equivalent to taking a dot product with this kernel centered around the current position:
0, 1, 0
1,-4, 1
0, 1, 0
Can this be vectorised as a dot product?
I think you want something like:
import numpy as np
from scipy.ndimage import convolve
length_l = 10
time_l = 10
u = np.zeros((length_l, length_l))# (x,y)
u[:, 0] = 1
u[:, -1] = 1
alpha = .1
weights = np.array([[ 0, 1, 0],
[ 1, -4, 1],
[ 0, 1, 0]])
for i in range(5):
u += alpha * convolve(u, weights)
print(u)
You could reduce down a bit by doing:
weights = alpha * weights
weights[1, 1] = weights[1, 1] + 1
for i in range(5):
u = convolve(u, weights)
print(u)

Categories

Resources