Householder Reflection of a vector - python-3.x

I want to construct a Householder reflection of a vector. My attempt is below according to the algorithm.
import math
import numpy as np
def vector_norm(n , vec):
result = 0
for k in range (n ):
result = result + vec[k] * vec[k]
return math.sqrt(result)
def householder(vec):
#vec the vector to be transformed
vec = np.asarray(vec, dtype=float)
if vec.ndim != 1:
raise ValueError("vec.ndim = %s, expected 1" % vec.ndim)
n = len(vec)
I = np.eye(n)
e1 = np.asarray(([0.0]*n),dtype=float)
e1[0] = 1.0
V1 = vec - vector_norm(n , vec)*e1
V_trans = np.array([V1])
H = I - 2 * ((V_trans.T # V_trans) / vector_norm( n ,V1))
return V1 , H
However, when I check;
v = np.array([1, 2, 3])
v1, h = householder(v)
assert_allclose(np.dot(h, v1), v)
assert_allclose(np.dot(h, v), v1)
The result is wrong.
AssertionError:
Not equal to tolerance rtol=1e-07, atol=0
(mismatch 100.0%)
x: array([ 22.095208, -16.118139, -24.177209])
y: array([1, 2, 3])

Related

Interpolation function for single data point

I'm using the interp1d function for interpolation
from scipy.interpolate import interp1d
x = [0, 3, 6, 10, 15, 20]
y = [1.87, 1.76, 1.27, 1.185, 0.995, 0.855]
f = interp1d(x, y, bounds_error=False)
x_find = [0, 5, 8, 10, 28]
print(f(x_find))
Using bounds_error=False in f = interp1d(x, y, bounds_error=False) returns nan value for x=28 in x_find.
Since interp1d raises an error for single datapoints, I tried the following for single datapoint.
x0 = [1.87]
y0 = [0.93]
f0 = lambda x: y0[0] if np.isclose(x, x0[0]) else np.NaN
print(f0(x0[0]))
This doesn't work when I try f0(x_find).
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Expected output:
f0(x_find) returns nan for values of x in x_find not present in x0like how bounds_error works.
Suggestions on how to do this will be really helpful
EDIT:
Question:
Would it be possible to modify the interpolation function of the single datapoint so that we could do just f(x_find), something similar to the one returned by f = interp1d() ?
I just only guess that you are missing a very simple thing: to put a single value to the f0() function using a list comprehension to get all values in case of a list with values.
Does the following code:
import numpy as np
from scipy.interpolate import interp1d
x = [0, 3, 6, 10, 15, 20]
y = [1.87, 1.76, 1.27, 1.185, 0.995, 0.855]
f = interp1d(x, y, bounds_error=False)
x_find = [0, 5, 8, 10, 28]
print(f(x_find))
x0 = [1.87]
y0 = [0.93]
f0 = lambda x: y0[0] if np.isclose(x, x0[0]) else np.NaN
print(f0(x0[0]))
print([f0(x) for x in x_find])
which prints:
[1.87 1.43333333 1.2275 1.185 nan]
0.93
[nan, nan, nan, nan, nan]
meet your expectations?
You can also redefine f0 to cover the case of passing a list of values to it as follows:
def f0(x):
import numpy as np
x0 = [1.87]
y0 = [0.93]
f = lambda x: y0[0] if np.isclose(x, x0[0]) else np.NaN
if isinstance(x, list):
return [f(z) for z in x]
elif isinstance(x, float):
return f(x)
else:
return "f0() accepts only float and lists of floats as parameter"
print('---')
print(f0(1.87))
print(f0(x_find))
print(f0("5"))
The output of the code above is:
---
0.93
[nan, nan, nan, nan, nan]
f0() accepts only float and lists of floats as parameter
FINALLY you can also redefine f0 as f_i which is a bit complex code simulating the behavior of scipy interp1d as follows:
def f_i(X=[0, 1.87], Y=[1.87, 0.93], bounds_error=False):
# ToDo: implementation of bounds_error evaluation
def f_interpolate(u):
assert len(X) > 1
XY = list(zip(X, Y))
XY.sort()
if not (XY[0][0] <= u <= XY[-1][0]):
return None
x_new = u
for i in range(len(XY)-1):
if XY[i][0] <= u <= XY[i+1][0]:
x_lo = XY[i ][0]
x_hi = XY[i+1][0]
y_lo = XY[i ][1]
y_hi = XY[i+1][1]
if x_new == x_lo:
return y_lo
if x_new == x_hi:
return y_hi
slope = (y_hi - y_lo) / (x_hi - x_lo)
y_new = y_lo + slope*(x_new - x_lo)
return y_new
return None
def f(v):
assert len(X) == 1
if v == X[0]:
return Y[0]
else:
return None
def r_f(w):
f_l = f_interpolate if len(X) > 1 else f
if isinstance(w, list):
return [f_l(z) for z in w]
elif isinstance(w, float):
return f_l(w)
else:
return "ValueErrorMessage: param. not float or list of floats"
return r_f
y = [1.87, 1.76, 1.27, 1.185, 0.995, 0.855]
x = [ 0, 3, 6, 10, 15, 20 ]
y0 = [0.93]
x0 = [1.87]
print('---')
f = f_i(x0, y0)
print(f(1.87))
f = f_i(x, y)
x_find = [0, 5, 8, 10, 28]
print(f(x_find))
print(f("5"))
which gives following output:
---
0.93
[1.87, 1.4333333333333333, 1.2275, 1.185, None]
ValueErrorMessage: param. not float or list of floats

Multiplication of polynomials

I have polynomial coefficients. How to get a list of coefficients e.g. by multiplying 10 polynomials?
For example for two polynomials.
(x + 2)*(x + 2) = x^2 + 4x + 4
[1,2] * [1,2] = [1, 4, 4]
I am trying to solve a codewars task which gives me a list of roots and I have to return a polynomial.
My first idea was function from numpy, poly but there is too much difference with large numbers. Thank u!
Source: https://www.codewars.com/kata/5b2d5be2dddf0be5b00000c4
My code:
import re
from numpy import poly
from math import fabs
def polynomialize(roots):
result = ''
data = list(filter(lambda x : x[0] != 0, zip(poly(roots).tolist(), range(len(roots), -1, -1))))
for coe, power in data:
if coe > 0:
result += f'+ {int(coe)}x^{power} '
else:
result += f'- {int(fabs(coe))}x^{power} '
result = re.sub(r'(x\^1)(?![0-9]+)', 'x', result).replace('x^0', '')
result = re.sub(r'(?<![0-9])(1x)','x', result)
return result[2:] + '= 0'
This is likely related to the integer type that numpy uses in its arrays, while the inputs and the resulting coefficients may involve greater numbers than these integers can hold (wrapping around).
You could do this to get data:
coeff = [1]
for r in roots:
coeff = [t[1] - r * t[0] for t in zip(coeff + [0], [0] + coeff)]
data = list(filter(lambda x : x[1] != 0,
reversed(list(enumerate(coeff)))))
for power, coe in data: # notice the pairs are in reverse compared to your loop
Also fabs is limited to integer. I would change int(fabs(coe)) to -int(coe).
I submitted this solution and it was accepted:
import re
def polynomialize(roots):
coeff = [1]
for r in roots:
coeff = [t[1] - r * t[0] for t in zip(coeff + [0], [0] + coeff)]
data = list(filter(lambda x : x[1] != 0,
reversed(list(enumerate(coeff)))))
result = ''
for power, coe in data:
if coe > 0:
result += f'+ {int(coe)}x^{power} '
else:
result += f'- {-int(coe)}x^{power} '
result = re.sub(r'(x\^1)(?![0-9]+)', 'x', result).replace('x^0', '')
result = re.sub(r'(?<![0-9])(1x)','x', result)
return result[2:] + '= 0'
Is it what you want?
from sympy import symbols, Poly
x = symbols("x")
pol1 = Poly(x + 2)
pol = pol1 ** 2
pol.all_coeffs()
# [1, 4, 4]

I'm stuck with GurobiError: Unable to convert argument to an expression

Could you help me with the
GurobiError: Unable to convert argument to an expression
I tried to declare variables as single variables (e.g x1, x2, x3 etc.), but then I thought the iterable objects will work better (as there was 'Non-itereable object' error), but still Gurobi cannot convert the expression; It now only throws an error at the #96, but I still can't find What should I do?
My code:
import gurobipy as grb
f = [5.5, 5.2, 5]
s = 3.8
lX = [0, 0, 0]
uX = [45000, 4000, 1000000]
lV = [0, 0]
lY = [0, 0]
uY = [1000000, 30000]
r = [3.25, 3.4]
pProc = 0.35
pConv = 0.25
p = [5.75, 4.0]
OreProcessingModel = grb.Model(name="MIP Model")
OreProcessingModel.ModelSense = grb.GRB.MAXIMIZE
x = {i: OreProcessingModel.addVar(vtype=grb.GRB.CONTINUOUS,
lb=lX[i],
ub= uX[i],
name="x_{0}".format(i))
for i in range(3)}
v = {i: OreProcessingModel.addVar(vtype=grb.GRB.CONTINUOUS,
lb=lV[i],
name="v_{0}".format(i))
for i in range(2)}
y = {i: OreProcessingModel.addVar(vtype=grb.GRB.CONTINUOUS,
lb=lY[i],
ub=uY[i],
name="v_{0}".format(i))
for i in range(2)}
conv = OreProcessingModel.addVar(vtype=grb.GRB.CONTINUOUS, lb=0, ub=50000, name="conv")
vlms2 = [v[0], v[1]]
vlmsitrtr = 2
constraint_1 = {1:
OreProcessingModel.addConstr(
lhs=grb.quicksum(y[i] for i in range(2)),
sense=grb.GRB.LESS_EQUAL,
rhs=100000,
name="constraint_{1}")
}
constraint_2 = {1:
OreProcessingModel.addConstr(
lhs=grb.quicksum(v[i] for i in range(2)),
sense=grb.GRB.LESS_EQUAL,
rhs=50000,
name="constraint_{2}")
}
OreProcessingModel.setObjective(grb.quicksum((f[i] * x[i] + s * v[i]) - (y[i]*r[i] + pProc*(y[i]) + pConv*conv))for i in range(3))
OreProcessingModel.optimize()
print(OreProcessingModel)
You should not work with dictionaries like that. You can turn this code
x = {i: OreProcessingModel.addVar(vtype=grb.GRB.CONTINUOUS,
lb=lX[i],
ub= uX[i],
name="x_{0}".format(i))
for i in range(3)}
into this:
x = OreProcessingModel.addVars(len(lX), vtype=grb.GRB.CONTINUOUS, lb=lX, ub=uX, name="x")
Furthermore, the dimensions of your variables don't match. You are looping over range(3) in the setObjective() call and try to access v[i] and y[i] but these dicts are only of length 2.

TypeError: Cannot cast array data from dtype('O') to dtype('int64') according to the rule 'safe'

When I run code below, I get:
TypeError: Cannot cast array data from dtype('O') to dtype('int64') according to the rule 'safe'
But I don't know where is dtype('O') and dtype('int64'). Does anyone know where is to parse?
import collections
import numpy as np
import math
import pandas as pd
def pre_prob(y):
y_dict = collections.Counter(y)
pre_probab = np.ones(2)
for i in range(0, 2):
pre_probab[i] = y_dict[i]/y.shape[0]
return pre_probab
def mean_var(X, y):
n_features = X.shape[1]
m = np.ones((2, n_features))
v = np.ones((2, n_features))
n_0 = np.bincount(y)[np.nonzero(np.bincount(y))[0]][0]
x0 = np.ones((n_0, n_features))
x1 = np.ones((X.shape[0] - n_0, n_features))
k = 0
for i in range(0, X.shape[0]):
if y[i] == 0:
x0[k] = X[i]
k = k + 1
k = 0
for i in range(0, X.shape[0]):
if y[i] == 1:
x1[k] = X[i]
k = k + 1
for j in range(0, n_features):
m[0][j] = np.mean(x0.T[j])
v[0][j] = np.var(x0.T[j])*(n_0/(n_0 - 1))
m[1][j] = np.mean(x1.T[j])
v[1][j] = np.var(x1.T[j])*((X.shape[0]-n_0)/((X.shape[0]- n_0) - 1))
return m, v # mean and variance
def prob_feature_class(m, v, x):
n_features = m.shape[1]
pfc = np.ones(2)
for i in range(0, 2):
product = 1
for j in range(0, n_features):
product = product * (1/math.sqrt(2*3.14*v[i][j])) * math.exp(-0.5* pow((x[j] - m[i][j]),2)/v[i][j])
pfc[i] = product
return pfc
def GNB(X, y, x):
m, v = mean_var(X, y)
pfc = prob_feature_class(m, v, x)
pre_probab = pre_prob(y)
pcf = np.ones(2)
total_prob = 0
for i in range(0, 2):
total_prob = total_prob + (pfc[i] * pre_probab[i])
for i in range(0, 2):
pcf[i] = (pfc[i] * pre_probab[i])/total_prob
prediction = int(pcf.argmax())
return m, v, pre_probab, pfc, pcf, prediction

IndexError: too many indices for array in Scipy.Optimize

I'm trying to debbug some code with Scipy.Optimize.
The bug comes from the constante: the optimisation works fine without it. The constante itself seems to works fine outside scipy.optimize (the variable testconst is computed normally). The code is the following:
from scipy.optimize import minimize
import numpy as np
def totaldist(dy):
n = np.shape(dy)[0]
temp = 0
for i in range(n):
temp += dy[i] ** 2
return -0.5 * temp
def create_bond(dy_max):
n = np.shape(dy_max)[0]
bond = np.zeros((n, 2))
for i in range(n):
bond[i, :] = [0, dy_max[i]]
tot = tuple([tuple(row) for row in bond])
return tot
# def create_const(type_x, dx, gamma, P):
def create_const(dy, *args):
arg = np.asarray(args)
n = np.shape(dy)[0]
dx = np.zeros((n, 2))
bnd = np.zeros((n, 2))
# from args to numpy array
type_x = np.zeros(n)
dP = 0
delta1 = np.zeros(n)
delta2 = np.zeros(n)
gamma = np.zeros((n, n))
for i in range(n):
a, b = bndr(arg[0, i])
delta1[i] = arg[0, i + n + 1]
delta2[i] = arg[0, i + 2*n + 1]
dx[i, 0] = (b - a) * dy[i]
gamma = GammaApprox(delta1, delta2, dx[:, 1], dx[:, 0])
d = np.dot(delta2, dx[:, 0])
g = np.dot(dx[:, 0], gamma)
g = np.dot(g, dx[:, 0])
dP = float(arg[0, n])
return d + 0.5 * g - dP
def GammaApprox(delta1, delta2, x1, x2):
n = np.shape(delta1)[0]
gamma = np.zeros((n, n))
for i in range(n):
if x2[i] == x1[i]:
gamma[i, i] = 0
else:
gamma[i, i] = (delta2[i] - delta1[i]) / (x2[i] - x1[i])
return gamma
def GetNewPoint(x1, x2, delta1, delta2, type_x, P):
n = np.shape(delta1)[0]
dmax = np.zeros(n)
dy0 = np.zeros(n)
# create the inequality data and initial points
for i in range(n):
a, b = bndr(type_x[i])
if x2[i] > x1[i]:
dmax[i] = (x2[i] - x1[i])/(b - a)
dy0[i] = 1 / (b - a) * (x2[i] - x1[i]) / 2
else:
dmax[i] = (x1[i] - x2[i])/(b - a)
dy0[i] = 1 / (b - a) * (x1[i] - x2[i]) / 2
bond = create_bond(dmax)
# create the args tuple
arg = ()
# type x
for i in range(n):
arg = arg + (type_x[i],)
# dP
arg = arg + (abs(P[0] - P[1]), )
# delta1
for i in range(n):
arg = arg + (delta1[i], )
# delta1
for i in range(n):
arg = arg + (delta2[i], )
testconst = create_const(dy0, arg)
# create the equality constraint
con1 = {'type': 'eq', 'fun': create_const}
cons = ([con1, ])
solution = minimize(totaldist, dy0, args=arg, method='SLSQP', bounds=bond, constraints=cons, options={'disp': True})
x = solution.x
print(x)
return x
def bndr(type_x):
if type_x == 'normal':
x_0 = -5
x_f = 1.5
if type_x == 'lognorm':
x_0 = 0.0001
x_f = 5
if type_x == 'chisquare':
x_0 = 0.0001
x_f = (0.8 * (10 ** .5))
return x_0, x_f
def test():
x1 = np.array([0.0001, 0.0001, -5])
x2 = np.array([1.6673, 0.84334, -5])
delta1 = np.array([0, 0, 0])
delta2 = np.array([2.44E-7, 2.41E-6, 4.07E-7])
type_x = np.array(['lognorm', 'chisquare', 'normal'])
P = (0, 6.54E-8)
f = GetNewPoint(x1, x2, delta1, delta2, type_x, P)
return f
test()
the error message is the following:
Traceback (most recent call last):
File "D:/Anaconda Project/TestQP - Simplified/QP.py", line 134, in <module>
test()
File "D:/Anaconda Project/TestQP - Simplified/QP.py", line 130, in test
f = GetNewPoint(x1, x2, delta1, delta2, type_x, P)
File "D:/Anaconda Project/TestQP - Simplified/QP.py", line 103, in GetNewPoint
solution = minimize(totaldist, dy0, args=arg, method='SLSQP', bounds=bond, constraints=cons, options={'disp': True})
File "C:\Program Files\Anaconda\lib\site-packages\scipy\optimize\_minimize.py", line 458, in minimize
constraints, callback=callback, **options)
File "C:\Program Files\Anaconda\lib\site-packages\scipy\optimize\slsqp.py", line 311, in _minimize_slsqp
meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['eq']]))
File "C:\Program Files\Anaconda\lib\site-packages\scipy\optimize\slsqp.py", line 311, in <listcomp>
meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['eq']]))
File "D:/Anaconda Project/TestQP - Simplified/QP.py", line 40, in create_const
a, b = bndr(arg[0, i])
IndexError: too many indices for array
I find roughly similar error in the website like: IndexError: index 1 is out of bounds for axis 0 with size 1/ForwardEuler
...but I failed to see it's really the same problem.
args is not passed to constraint-functions (automatically)!
This is indicated in the docs:
args : tuple, optional
Extra arguments passed to the objective function and its derivatives (Jacobian, Hessian).
You can see the problem easily by adding a print:
def create_const(dy, *args):
print('args:')
print(args)
arg = np.asarray(args)
...
which will output something like:
args:
(('lognorm', 'chisquare', 'normal', 6.54e-08, 0, 0, 0, 2.4400000000000001e-07, 2.4099999999999998e-06, 4.0699999999999998e-07),)
args:
()
ERROR...
If you remove your test (which is manually passing args; which works) testconst = create_const(dy0, arg), you will see only the non-working output:
args:
()
ERROR...
Constraints have their own mechanism of passing args as described in the docs:
constraints : dict or sequence of dict, optional
Constraints definition (only for COBYLA and SLSQP). Each constraint is defined in a dictionary with fields:
type : str
Constraint type: ‘eq’ for equality, ‘ineq’ for inequality.
fun : callable
The function defining the constraint.
jac : callable, optional
The Jacobian of fun (only for SLSQP).
args : sequence, optional
Extra arguments to be passed to the function and Jacobian.
Equality constraint means that the constraint function result is to be zero whereas inequality means that it is to be non-negative. Note that COBYLA only supports inequality constraints.
In your case:
con1 = {'type': 'eq', 'fun': create_const} # incomplete!
con1 = {'type': 'eq', 'fun': create_const, 'args': (arg,)} # (,)
# to make it behave as needed
# for your code!
This will make it run until some other problem occurs!

Resources