I'm trying to run a minimization problem using scipy.optimize, including a NonlinearConstraint. I really don't want to code derivatives myself, so I'm using autograd to do it. But even though I follow the exact same procedure for the arguments to minimize and to NonlinearConstraint, the first seems to work and the second doesn't.
Here's my MWE:
useconstraint = False
import autograd
import autograd.numpy as np
from scipy import optimize
def function(x): return x[0]**2 + x[1]**2
functionjacobian = autograd.jacobian(function)
functionhvp = autograd.hessian_vector_product(function)
def constraint(x): return np.array([x[0]**2 - x[1]**2])
constraintjacobian = autograd.jacobian(constraint)
constrainthvp = autograd.hessian_vector_product(constraint)
constraint = optimize.NonlinearConstraint(constraint, 1, np.inf, constraintjacobian, constrainthvp)
startpoint = [1, 2]
bounds = optimize.Bounds([-np.inf, -np.inf], [np.inf, np.inf])
print optimize.minimize(
function,
startpoint,
method='trust-constr',
jac=functionjacobian,
hessp=functionhvp,
constraints=[constraint] if useconstraint else [],
bounds=bounds,
)
When I turn useconstraint off (at the top), it works fine and minimizes at (0, 0) as expected. When I turn it on, I get the following error:
Traceback (most recent call last):
File "test.py", line 29, in <module>
bounds=bounds,
File "/home/heshy/.local/lib/python2.7/site-packages/scipy/optimize/_minimize.py", line 613, in minimize
callback=callback, **options)
File "/home/heshy/.local/lib/python2.7/site-packages/scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py", line 336, in _minimize_trustregion_constr
for c in constraints]
File "/home/heshy/.local/lib/python2.7/site-packages/scipy/optimize/_constraints.py", line 213, in __init__
finite_diff_bounds, sparse_jacobian)
File "/home/heshy/.local/lib/python2.7/site-packages/scipy/optimize/_differentiable_functions.py", line 343, in __init__
self.H = hess(self.x, self.v)
File "/home/heshy/.local/lib/python2.7/site-packages/autograd/wrap_util.py", line 20, in nary_f
return unary_operator(unary_f, x, *nary_op_args, **nary_op_kwargs)
File "/home/heshy/.local/lib/python2.7/site-packages/autograd/differential_operators.py", line 24, in grad
vjp, ans = _make_vjp(fun, x)
File "/home/heshy/.local/lib/python2.7/site-packages/autograd/core.py", line 10, in make_vjp
end_value, end_node = trace(start_node, fun, x)
File "/home/heshy/.local/lib/python2.7/site-packages/autograd/tracer.py", line 10, in trace
end_box = fun(start_box)
File "/home/heshy/.local/lib/python2.7/site-packages/autograd/wrap_util.py", line 15, in unary_f
return fun(*subargs, **kwargs)
File "/home/heshy/.local/lib/python2.7/site-packages/autograd/differential_operators.py", line 88, in vector_dot_grad
return np.tensordot(fun_grad(*args, **kwargs), vector, np.ndim(vector))
File "/home/heshy/.local/lib/python2.7/site-packages/autograd/tracer.py", line 44, in f_wrapped
ans = f_wrapped(*argvals, **kwargs)
File "/home/heshy/.local/lib/python2.7/site-packages/autograd/tracer.py", line 48, in f_wrapped
return f_raw(*args, **kwargs)
File "/home/heshy/.local/lib/python2.7/site-packages/numpy/core/numeric.py", line 1371, in tensordot
raise ValueError("shape-mismatch for sum")
ValueError: shape-mismatch for sum
What am I doing wrong? I think the issue is in the hessian_vector_product because I see hess in the error message, but I'm not sure about that.
Ok, I found the answer. This was very confusing.
The hessp argument to minimize expects a function that returns the "Hessian of objective function times an arbitrary vector p" (source). By contrast, the hess argument to NonlinearConstraint expects "A callable [that] must return the Hessian matrix of dot(fun, v)" (source).
If you interpret the first quote like I did, "Hessian of (objective function times an arbitrary vector p)", it means pretty much the same thing as "Hessian matrix of dot(fun, v)". I therefore assumed you could use the same autograd function for both.
However, the correct interpretation is "(Hessian of objective function) times an arbitrary vector p", which is completely different. The hessian_vector_product function in autograd gives the correct result for the first, but you need a different function for the second.
I have a list which looks like this,
data_raw=[[], [7944, -11896, 3376, 1627, -850, -3991], [8688, -12192, 1936,1404, -616, -3536], [6540, -11800, 1608, 3021, 780, -1061], [6804, -11864, 3828, 4310, 552, -2343], [7208, -12544, 3768, 2542, 286, 1264], [7048, -14532, 6824, 2528, 1577, 2583], [6112, -17376, 10180, 132, -1716, 1001], [7576, -21140, 6796, -1725, 1657, 1980], [2928, -31716, 15400, -5945, 824, -3558], [8940, -24016, 11540, -12047,-5574, -16019], [12020, -17516, 3744, -14637, 1521, -14791], [8916, -16160, 5860, -14122, -3793, -13597], [10144, -8124, 1076, -12027, -1194, -8809], [8088, -7264, 928, -18441, -2058, -80], [7684, -4896, -5224, -9800, 2427, 2054], [2040, -7776, -3520, -9306, 4442, 1276], [6240, -7340, -7216, -1757, -3630, -2734], [5720, -3940, -4632, -901, 1469, -1682], [5244, -4676, -5648, 2720, 3526, -436], [4016, -5336, -2976, 4280, 4543, -1562], [4028, -5156, -5560, 7391, 5000, -1317], [748, -9800, -2144, 10353, 6616, -3390], [10268, -7220, 1844, 11657, 8566, -4740], [11300, -10752, 4508, 11666, 10771, -1356], [16792, -10180, 24476, 13474, 2828, -5205], [19208, -10908, 6636, 9747, 10501, 1676], [7540, -20480, 13248, 8715, 12607, 7017], [15780, -20832, 11600, 5686, 4737, -3654], [18004, -20072, 17716, 1082, 2218, -3181], [16516, -18528, 14568, -3931, -5457, -4260], [15596, -12596,9084, -7735, -8646, -4221], [13296, -8948, 6316, -9215, -8260, -3225], [10860, -8124, 6116, -7264, -7653, -678], [7968, -7828, 5384, -8604, -7043, 1076], [8008, -5316, 1816, -6457, -7414, -50], [9304, -3568, 1092, -4895, -4654, 3123], [9560, -3932, -352, -904, -6369, 1981], [14692, -3168, 836, 2406, -8099, 3121], [13088, -6292, 44, 5503, -11759, 6405], [11892, -8316, -836, 6159, -8673, 10130], [8252, -13220, -1064, 8279, -7906, 12090], [3572, -18392, -1536, 5995, -2719, 10667], [2864, -19576, 960, 6207, -4501, 6554], [1024, -20140, -1964, 7834, -10817, 5197]]
When i use this code:
data = np.array(data_raw).astype(float)
I got an error:
>> Traceback (most recent call last):
data = np.array(data_raw).astype(float)
ValueError: setting an array element with a sequence.
Does anyone know why this error occurred?
The first element of your 2D list is an empty list, causing this issues. If you remove it or just use
data = np.array(data_raw[1:]).astype(float)
it will work as intended.
I am trying to get Chapel to return an integer to Python. I'd like to call it with python call.py.
call.py
import os
from pych.extern import Chapel
currentloc = os.path.dirname(os.path.realpath(__file__))
#Chapel(sfile=os.path.join(currentloc + '/response.chpl'))
def flip_bit(v=int):
return int
if __name__=="__main__":
u = 71
w = flip_bit(u)
print(w)
And response.chpl
export
proc flip_bit(v: int) :int {
v = -v;
return v;
}
This returns the error
/tmp/temp-7afvL9.chpl:2: In function 'flip_bit':
/tmp/temp-7afvL9.chpl:3: error: illegal lvalue in assignment
g++: error: /tmp/tmpvmKeSi.a: No such file or directory
Traceback (most recent call last):
File "call.py", line 15, in <module>
w = flip_bit(u)
File "/home/buddha314/.virtualenvs/pychapel/local/lib/python2.7/site-packages/pych/extern.py", line 212, in wrapped_f
raise MaterializationError(self)
pych.exceptions.MaterializationError: Failed materializing ({'anames': ['v'],
'atypes': [<type 'int'>],
'bfile': None,
'dec_fp': '/home/buddha314/pychapel/tmp/response.chpl',
'dec_hs': '7ecfac2d168f3423f7104eeb38057ac3',
'dec_ts': 1502208246,
'doc': None,
'efunc': None,
'ename': 'flip_bit',
'lib': 'sfile-chapel-7ecfac2d168f3423f7104eeb38057ac3-1502208246.so',
'module_dirs': [],
'pfunc': <function flip_bit at 0x7fa4d72bd938>,
'pname': 'flip_bit',
'rtype': <type 'int'>,
'sfile': '/home/buddha314/pychapel/tmp/response.chpl',
'slang': 'chapel',
'source': None}).
UPDATE
Based on Lydia's response, I did
export
proc flip_bit(v: int) :int {
var w: int;
w = -v;
return w;
}
And that worked! WOO-HOOO!!!!
UPDATE 2
Based on Brad's comments, this also works
export
proc flip_bit(in v: int) :int {
return -v;
}
Perhaps he can add a comment on benefits of each approach.
It looks like your issue is that you're trying to modify the argument before returning it. Chapel's default argument intent for integers is const in ( see the Chapel spec http://chapel.cray.com/docs/latest/language/spec.html, section 13.5 ), which means it can't be modified within the body of the function and is a copy of the value passed to it. If you store the result in a local variable and return that instead, that should solve your compilation failure and give you the behavior you desire.
I wrote a script to do interpolation
import scipy.interpolate
import csv
inputfile1 = 'test.csv'
outputfile = 'Day1_out.csv'
distance_list = []
EC_list = []
new_dist_list=[]
outfile = open(outputfile,'w')
outfile.write('Distance,EC\n')
with open (inputfile1,'rb') as csvfile:
f1 = csv.reader(csvfile,delimiter=',')
next(f1) #skip header line
for row in f1:
dist = row[12]
EC=row[13]
distance_list.append(dist)
EC_list.append(EC)
y_interp = scipy.interpolate.interp1d(distance_list,EC_list)
new_dist = 561.7
end = 560.2
while new_dist>end:
new_dist_list.append(dist)
new_dist=new_dist-0.2
for distance in new_dist_list:
EC=y_interp(distance)
outfile.write(str(distance)+','+str(EC)+'\n')
outfile.close()
When I ran the script it gave me the error message
Traceback (most recent call last):
File "D:\14046\Scripts\interpolation_RoR.py", line 41, in <module>
EC=y_interp(distance)
File "C:\Python27\lib\site-packages\scipy\interpolate\polyint.py", line 54, in __call__
y = self._evaluate(x)
File "C:\Python27\lib\site-packages\scipy\interpolate\interpolate.py", line 448, in _evaluate
out_of_bounds = self._check_bounds(x_new)
File "C:\Python27\lib\site-packages\scipy\interpolate\interpolate.py", line 474, in _check_bounds
if self.bounds_error and below_bounds.any():
AttributeError: 'bool' object has no attribute 'any'
Anyone has any idea where I have errors?
BTW, the input file have these values for distance and EC
Distance,EC
561.8,450
561.78,446
561.7,444
561.2,440
561.02,438
560.5,437
560.1,435
Thanks,
We are getting the same error message here. I think this does not necessarily need to be a problem with your code.
In our case switching to SciPy version 0.15.0 instead of 0.13.x solves the problem.
So it looks like the current version of SciPy accepts a wider range of input values.