I am having a problem with calling a function twice. If I comment my last 3 lines and keep show(), I don't get any errors and things come as they are suppose to. However, if I don't comment them out calling the last function again gives me this error:
Traceback (most recent call last):
File "second_1.py", line 29, in <module>
domega=c_d(len(t),t,z)
File "second_1.py", line 25, in c_d
dy[1:-1]=(y[2:]-y[0:-2])/(x[2:]-x[0:-2])
TypeError: unsupported operand type(s) for -: 'list' and 'list'
Here is the function:
import numpy as np
from pylab import *
import time
t_initial=time.time()
clf()
t,hp,hn= np.loadtxt("Richardson.dat", usecols=(0,1,2),comments='#', unpack=True) # to select just a few columns
print(time.time()-t_initial)
def phi(y,x):
return(np.arctan(y/x))
phase=[0.0]*len(t)
phase=phi(hp[0:],hn[0:])
#plot(t,phase)
#show()
def c_d(order,x,y):
dy=[0.0]*order
dy[0]=(y[1]-y[0])/(x[1]-x[0])
dy[-1]=(y[-1]-y[-2])/(x[-1]-x[-2])
dy[1:-1]=(y[2:]-y[0:-2])/(x[2:]-x[0:-2])
return(dy);
z=c_d(len(t),t,phase);
plot(t,z)
print(len(z)-len(t))
domega=c_d(len(t),t,z)
plot(t,domega)
show()
The problem is very clearly explained in the error message:
The '-' operand is not applicable for the type list.
(y[2:]-y[0:-2])/(x[2:]-x[0:-2])
y[2:] slices a list and returns a list. y[0:-2] slices also a list and returns a list. So there you have 2 lists.
y[2:] (a list) -(your operator) y[0:-2] (a list)
And list - list is not defined (there is no syntax for: 'listObject' - 'listObject').
BUT: the + operator is defined for lists (example):
l = ["ja"]
m = ["nein"]
n = l + m
print n
# output: ['ja', 'nein']
Take a look here for these different kind of possible operators:
https://docs.python.org/2/library/stdtypes.html
As explained in the other answers, you can not subtract regular Python lists. So why does it work the first time, and fails the second? Let's take a look at the code.
t, hp, hn = np.loadtxt(...)
...
def c_d(order, x, y):
dy = [0.0] * order
dy[ 0] = (y[1] -y[0]) / (x[ 1]-x[0])
dy[-1] = (y[-1]-y[-2]) / (x[-1]-x[-2])
dy[1:-1] = (y[2:]-y[0:-2]) / (x[2:]-x[0:-2])
return dy
z = c_d(len(t), t, phase)
...
domega = c_d(len(t), t, z)
...
When you first call c_d, the parameters x and y seem to be numpy arrays (at least t and phase are results of numpy function calls), and for those, - is a legal operation. But inside c_d, you create and finally return a regular Python list, dy, so when you then call c_d again with the result of the first call as y, this part y[2:]-y[0:-2] will fail, as y now is a regular list.
Make sure your dy is a numpy array, too, i.e. dy = np.array([0.0] *order) or just dy = np.zeros(order), then it should work.
As stated by Cyber and ProgrammingIsAwsome the error is on line
(y[2:]-y[0:-2])/(x[2:]-x[0:-2])
where you actually try to substract lists.
You could write explicitely :
for i in range(1, order - 1):
dy[i]=(y[i+1]-y[i-1])/(x[i+1]-x[1-1])
Related
I am trying to use Mystic to minimize a nonlinear function with linear constraints.
As a simple example, I have the following:
import numpy as np
import mystic.symbolic as ms
from mystic.symbolic import generate_constraint
from mystic.symbolic import generate_solvers
from mystic.symbolic import linear_symbolic
from mystic.monitors import Monitor
from mystic.solvers import LatticeSolver
from mystic.solvers import NelderMeadSimplexSolver
from mystic.termination import CandidateRelativeTolerance as CRT
# diamond-shaped constraint
# same format as output of mystic.linear_symbolic()
basic_constraint = '''
1.0*x0 + 1.0*x1 <= 5
1.0*x0 - 1.0*x1 >= -5
1.0*x0 + 1.0*x1 >= -5
1.0*x0 - 1.0*x1 <= 5
'''[1:]
def basic_objective(x, *args):
v1 = x[0] * x[1] / (1 + np.abs(x[0] + x[1]))
v2 = np.min(x)
return v1 + v2/(1+np.abs(v1))
When trying to run the code, I do the following:
def test_basic():
stepmon=Monitor()
nbins = [6,6,]
solver = LatticeSolver(len(nbins), nbins)
solver.SetNestedSolver(NelderMeadSimplexSolver)
print('Generating Solvers')
constraint_solver = generate_solvers(
basic_constraint,
nvars=2
)
print(constraint_solver)
# HERE IS ISSUE, IF COMMENTED ISSUE BELOW
print(constraint_solver[0](np.ones(2)))
print('Setting Constraints')
solver.SetConstraints(
generate_constraint(constraint_solver)
)
solver.SetGenerationMonitor(stepmon)
solver.SetTermination(CRT())
print('Solving...')
# ISSUE APPEARS HERE IF print(constraint_solver[0]...)
# IS COMMENTED OUT
solver.Solve(basic_objective)
solution = solver.Solution()
print(solution)
return solution
test_basic()
When I run the above, the error occurs at
print(constraint_solver[0](np.ones(2)))
or, if I comment it out,
solver.Solve(basic_objective)
The only noticeable difference is the size of the call stack.
The error I get is
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 12, in test_basic
File "<string>", line 4, in solver_139632515562208
File "<string>", line 1
SyntaxError: cannot assign to operator
This is a result of Mystic trying to compile Python code from a string and encountering a syntax error, but I do not know how to fix this issue.
I'm the mystic author. You are missing one key function, and a second that is not needed in this case but often is.
If you print the doc for your constraint solvers, you'll see that they are not formed well.
>>> constraint_solver = generate_solvers(basic_constraint, nvars=2)
>>> print(constraint_solver[0].__doc__)
1.0*x[0] - 1.0*x[1] = min(5 - (_tol(5,tol,rel) * any(equal(5,[]))), 1.0*x[0] - 1.0*x[1])
>>>
You need to isolate a single variable on the left-hand side. Hence, we either need to solve or simplify. For inequalities, simplify works better, and for equalities solve generally works. I am not sure the level of documentation that states that. Anyway, I use simplify before building the constraints.
>>> from mystic.symbolic import simplify
>>> constraint_solver = generate_solvers(simplify(basic_constraint), nvars=2)
>>> print(constraint_solver[0].__doc__)
x[0] = max(1.0*x[1] - 5.0 + (_tol(1.0*x[1] - 5.0,tol,rel) * any(equal(1.0*x[1] - 5.0,[]))), x[0])
>>>
>>> print(constraint_solver[0](np.ones(2)))
[1. 1.]
>>>
Now, your code works as expected.
However, I'd generally make one other modification.
>>> from mystic.constraints import and_
>>> c = generate_constraint(constraint_solver, join=and_)
>>> c(np.ones(2)*5)
[0.0, 5.0]
>>> print(c.__doc__)
inner: x[0] = max(1.0*x[1] - 5.0 + (_tol(1.0*x[1] - 5.0,tol,rel) * any(equal(1.0*x[1] - 5.0,[]))), x[0])
inner: x[0] = min(1.0*x[1] + 5.0 - (_tol(1.0*x[1] + 5.0,tol,rel) * any(equal(1.0*x[1] + 5.0,[]))), x[0])
inner: x[0] = min(5.0 - 1.0*x[1] - (_tol(5.0 - 1.0*x[1],tol,rel) * any(equal(5.0 - 1.0*x[1],[]))), x[0])
inner: x[0] = max(-1.0*x[1] - 5.0 + (_tol(-1.0*x[1] - 5.0,tol,rel) * any(equal(-1.0*x[1] - 5.0,[]))), x[0])
Without the join=and_, your code still works. The difference is that without an explicit join statement, it's assumed the constraints are independent of each other, and can be solved one at a time. Using join=and_ forces the constraints to be solved simultaneously, which is slower. There's also or_ and other more complex combinations in building constraints, but the default is to assume independence.
Both points are subtle, and, I believe, in the documentation it should state that the constraints solvers need the symbolic equations need to have a single variable isolated on the left-hand side. However, it's probably not obvious as that's often missed.
One of the tutorial questions has us focus on creating a function which returns a simple expression. The expression is below:
EQ = cos*(pi/2)*x^2 + sin(pi/4)*x + x^3
Where x is an array of floats.
I have written the following code to answer this:
def getStats(x):
# Complete the function.
y = float(numpy.cos((numpy.pi/2)*x**2) + numpy.sin((numpy.pi/4)*x) + x**3)
return y
However I get an error saying unsupported operand types for pow or ** list or int.
I have tried to type cast this but it has not worked.
Apart from type casting I have tried breaking this down further but have been unsuccessful. Any ideas on what I can try next?
Thank you.
You should evaluate the expression for each value of the input list. You can do this using list comprehension.
def getStats(X):
# Complete the function.
y = [float(numpy.cos((numpy.pi/2)*x**2) + numpy.sin((numpy.pi/4)*x) + x**3) for x in X]
return y
The approach in the edit section is preferred (see below).
Edit: Converting the input list to numpy array and do the computation.
def getStats(x):
# Complete the function.
x = numpy.array(x)
y = numpy.cos((numpy.pi/2) * numpy.power(x, 2)) + numpy.sin((numpy.pi/4)*x) + numpy.power(x, 3)
return y # if you want to return a list, use list(y)
Using the recent version of sympy (0.7.6) I get the following bad result when determining the integral of a function with support [0,y):
from sympy import *
a,b,c,x,z = symbols("a,b,c,x,z",real = True)
y = Symbol("y",real=True,positive=True)
inner = Piecewise((0,(x>=y)|(x<0)|(b>c)),(a,True))
I = Integral(inner,(x,0,z))
Eq(I,I.doit())
This is incorrect as the actual result should have the last two cases swapped. This can be confirmed by checking the derivative:
Derivative(I.doit(),z).doit().simplify().subs(z,x)
which reduces to 0 everywhere.
Interestingly, when dropping the condition (b>c) by substituting inner = Piecewise((0,(x>=y)|(x<0)),(a,True)) I get a TypeError:
TypeError: cannot determine truth value of
-oo < y
Am I using the library incorrectly or is this actually a serious sympy bug?
Yes, sympy 0.7.6 is wrong in this case, and in some other such cases. Generally, I don't know any symbolic math package that I would trust to do calculus with piecewise defined functions.
Note that although
inner = Piecewise((0, (x>=y)|(x<0)), (a,True))
throws a TypeError at integration time, a logically equivalent definition
inner = Piecewise((a, (x<y)&(x>=0)), (0,True))
leads to the correct result
Piecewise((a*z, And(z < y, z >= 0)), (0, And(z <= 0, z >= -oo)), (a*y, True))
By the way, the previous version, sympy 0.7.5, handles
inner = Piecewise( (0, (x>=y)|(x<0)), (a,True) )
without a TypeError, producing the correct result (in a different form):
Piecewise((0, z <= 0), (a*y, z >= y), (a*z, True))
Here is another, simpler example of buggy behavior:
>>> Integral(Piecewise((1,(x<1)|(z<x)), (0,True)) ,(x,0,2)).doit()
-Max(0, Min(2, Max(0, z))) + 3
>>> Integral(Piecewise((1,(x<1)|(x>z)), (0,True)) ,(x,0,2)).doit()
-Max(0, Min(2, Max(1, z))) + 3
The first result is incorrect (it fails for z=0, for example). The second is correct. The only difference between two formulas is z<x vs x>z.
So, I have this code
from __future__ import division, print_function
import sympy as sp
import numpy as np
from sympy.utilities.lambdify import *
u = np.random.uniform(4, 6, 500)
w, k = sp.symbols('w k')
f = sp.log((k - w) * sp.exp((k - w)**5))
l = sum(f.subs(dict(k=k)) for k in u)
And now I want to use l as a function of w. So I know of some options
z_lambdify = lambdify(w, l)
z_subs = lambda x: l.subs(w, x)
The first function gives an error
>>> z_lambdify(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
OverflowError: math range error
>>> z_lambdify(4)
40.862695278600114
While the second gives answers
>>> z_subs(1)
11469.9130597554
>>> z_subs(4)
40.8626952786003
I would just use this, but it is very slow. Any way to get around this (fixing the lamdify error or a way of using l as a function that is not so slow)?
Version: Python 2.7.6, NumPy 1.8.1, SymPy 0.7.4.1
Answering your question:
The problem is that:
z_lambdify = lambdify(w, l)
tells the new function to perform the calculations using the built-in math functions, which you can check running with cProfile.run('z_lambdify(1)'); while doing z_subs(1) calls sympy functions. To get the same behavior you should tell lambdify() to use the same module:
z_lambdify = lambdify(w, l, "sympy")
Important suggestion:
You should simplify your function already at its definition and then useNumPy to perform the calculations much more efficiently. Using some simple algebra your function can be rewritten in a "non-overflowing" format as:
f = lambda k, w: np.log(k - w) + (k - w)**5
such that your desired answer can be achieved doing:
f(k=u, w=1).sum()
when you do f(k=u, w=1) you get an array with the same shape of u, where each value represents the result of the function evaluated with each value of u. You can use this function to simultaneously evaluate f() for different values of k and w, i.e. passing w as another array with the same shape of u instead of using a constant value.
I am trying to write some code for an assignment in python. What I am not finding anywhere is what is wrong and why it will not run. It is sense and move robotic localization function. I do not understand why this line will not work.
q.append(p[i] * (hit * sensor_right + (1 - hit) * (1-sensor_right)))
hit = a comparison between two strings. That evaluates to true or false which is 1 or 0, right?
sensor_right = 0.7
Traceback (most recent call last):
File "vm_main.py", line 26, in <module> import main
File "/tmp/sbdxfjuois/main.py", line 50, in <module> p = sense(p, measurements[k])
File "/tmp/sbdxfjuois/main.py", line 34, in sense q.append(p[i] * (hit * sensor_right + (1 - hit) * (1-sensor_right)))
TypeError: can't multiply sequence by non-int of type 'float'
Can you suggest anything for what I have here posted?
def sense(p, Z):
q = [ ]
for i in range(len(p)):
hit = (Z == colors[i])
q.append(p[i] * (hit * sensor_right + (1 - hit) * (1-sensor_right)))
s = sum(q)
for i in range(len(q)):
q[i] = q[i]/s
return q
As others have pointed out, this p variable is apparently a sequence of sequences. You can verify this by putting
print(type(p))
print(type(p[i]))
before the append statement. You'll probably see something like
tuple
tuple
If that's what you expected, then you'll need to loop over the other index of the array. Also, does your q need to be returned with the same shape? I suspect you want something more like this.
def sense(p, Z):
q = p[:]
for i in range(len(p)):
for j in range(len(p[i])):
hit = (Z == colors[i])
q[i][j] = (p[i][j] * (hit * sensor_right + (1 - hit) * (1-sensor_right)))
s = sum(q)
for i in range(len(q)):
q[i] = q[i]/s
return q
Note that you also might want to look into numpy arrays.
If you're correct about the other variables, it is telling you that p[i] is a sequence (most likely a list), which can't be multiplied by a float. Perhaps p[i] is not what you're expecting it to be?
Try printing p[i] before the line that throws an error.
The problem here is what others have said. You can only multiply a sequence by an int, not a float.
For example
>>> [1] * 3
[1, 1, 1]
>>> "f" * 6
ffffff
>>> [1] * 0.7
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'
Double check your data type for p, to make sure it is supposed to be a sequence. If that is truly what p should be, then make sure to convert the following to an int before multiplying
(hit * sensor_right + (1 - hit) * (1-sensor_right))
Related to what #Mike said, you could also do:
q = []
sum = 0
for i in p:
sub_q = []
for val in i:
computed_val = val * (hit * sensor_right + (1 - hit) * (1-sensor_right))
sum += computed_val
sub_q.append(computed_val)
q.append(sub_q)
I like that because it is more concise and doesn't have to build a bunch of ranges every time you call it, and it also reduces the number of times you iterate over the data, but to each their own.