Programming a distance - python

First of all: I am by no means a Python expert, so this question is probably rather easy. Secondly, I worked over more than 2 hours on this and now I've decided I needed help. I want to implement a distance in Python. The distance is given as follows:
Where ui and uj are vectors that are given. d is the dimension of that vector. For example: if ui = (1,2,3), then ui_0= 1.
Now, this is what I've come up with so far: (here, xi = ui and xj = uj)
def dist(xi, xj, k):
distances = np.zeros(len(xi))
min1 = (0, 0)
min2 = (0, 0)
for dim in [0, len(xi)]:
for s in [-k, k]:
min1 = abs(xi[dim] - xj[dim + s])
min1[-k, k].min()
min2 = min(abs(xj[dim] - xi[dim + s]))
min2[-k, k].min()
distances = max(min1,min2)
but it doesn't work. Does anybody know where I've gone wrong?
Traceback:
Traceback (most recent call last): File "<input>", line 1, in
<module> File "<input>", line 8, in dist IndexError: invalid index
to scalar variable.
EDIT:
Ok, I tried to look at the case where k is maximal and I've taken the comments of Riley and Wouda into account. I came up with this piece of code:
def dist1(xi, xj):
for dim in range(len(xi)):
for s in range(-dim, len(xi) - dim):
return max(min(abs(xi[dim] - xj[dim + s])), min(abs(xj[dim] - xi[dim + s])))
and I still get the error:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 4, in dist1
TypeError: 'numpy.int64' object is not iterable
What is going on?

You appear to forget d is a parameter also (since you compute Dist_d^{ij}, where d is clearly a passed parameter). Together with k, I think the following represents the snippet of math you posted.
def dist(xi, xj, d, k):
min1 = min(abs(xi[d] - xj[d + s]) for s in range(-k, k + 1))
min2 = min(abs(xj[d] - xi[d + s]) for s in range(-k, k + 1))
return max(min1, min2)
Notice that Python will index negative values from the end of the list, which may or may not be what you want (in math, generally, not). So getting the arguments to this function right is a bit tricky, and you should build-in some checks to make sure all cases are handled correctly.

Related

Keep getting IndexError Message?

I'm trying to build out a project where I use exponential smoothing to predict the prices of commodities. I'm starting with basic exponential smoothing and am going to work my way up to triple exponential smoothing. However, when I use this code
with open('HistoricalData_1617379638571.csv', newline='') as f:
reader = csv.reader(f)
data = list(reader)
df = pd.read_csv('HistoricalData_1617379638571.csv')
df.columns = ['Date','Close/Last','Volume','Open','High','Low']
df.set_index('Date', inplace=True)
print(df)
x=df.loc[:,'Close/Last'].values
y=list(x)
z=[int(i) for i in y]
print(z)
alpha=0.9
def exp_smooth(alpha,z):
for i in z:
new_res=z.append((alpha * z[i] + (1 - alpha * z[i-1])))
print(new_res)
exp_smooth(alpha,z)
I keep getting the error message
Traceback (most recent call last):
File "main.py", line 38, in <module>
exp_smooth(alpha,z)
File "main.py", line 34, in exp_smooth
new_res=z.append((alpha * z[i] + (1 - alpha * z[i-1])))
IndexError: list index out of range
What am I doing wrong? How do I fix this so that my exponential smoothing function returns something other than an error?
When you try to index the list with values of the list, you may get a value which is not a valid index of the list. For example, if the list were z=[100000], the for loop would try to index z at index 1000000, which clearly does not exist.
You're probably looking to use range(len()):
def exp_smooth(alpha, z):
for i in range(len(z)):
new_res=z.append((alpha * z[i] + (1 - alpha * z[i-1])))
or, even better, enumerate():
def exp_smooth(alpha, z):
for index, value in enumerate(z):
new_res = z.append((alpha * value + (1 - alpha * z[index-1])))

Array is too big error in Python

I have this code in python:
from numpy import *
import itertools
m, n = 6, 10
set_m = [i + 1 for i in range(m + 1)]
comb = zeros(((m + 1) ** n, n), dtype=int)
k = 0
for i in itertools.product(set_m, repeat=n):
comb[k][:] = i
k += 1
But when I run it, I got this error:
Traceback (most recent call last):
File "main.py", line 33, in <module>
comb = zeros(((m + 1) ** n, n), dtype=int)
ValueError: array is too big.
If you are sure you MUST have a billion element array, and there is no way around it whatsoever (sometimes happens, but not every day), you can use memmap to create the array in the hard drive instead of the RAM memory. But I think it would be wise to search for ways to re-write your code to avoid doing such a slow thing.

Why does calling this function twice cause an error?

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])

Math domain error in fermat

from math import sqrt
def fermatBook (n):
x=int(sqrt(n))
c=x**2-n
while (sqrt(c)!=int(sqrt(c))):
x=x+1
y=sqrt(c)
a=x+y
b=x-y
if a==1 or b==1:
print "The number is prime"
return a, b
error:
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
fermatBook (23867)
File "C:/Python27/fermatLivro.py", line 6, in fermatBook
while (sqrt(c)!=int(sqrt(c))):
ValueError: math domain error
I don't know what is going wrong with the program... Could someone help me ?
most likely your variable c is going negative:
Example
if you call:
n = 2
fermatBook(n)
it will assign the following values to the following variables:
x = int(sqrt(n)) = int(1.47...) = 1
c = x**2 - n = 1**2 - 2 = 1 - 2 = -1
This will likely happen alot on values of n whose square root is not an integer.
sqrt(n) >= int(sqrt(n)), n >= 0
Then when you call sqrt(c) it is out of the domain because it cannot handle negative values.
>>> from math import sqrt
>>> sqrt(-1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
You should rather use something that can handle imaginary numbers, i.e. cmath
Or perform checks to assure this does not happen:
As an example...
if c < 0:
c = 0
As soon as you fix this however you are going to run into another problem:
This is an infinite loop:
while (sqrt(c)!=int(sqrt(c))):
x=x+1
you need to update c otherwise the condidtion will never change no matter how many times you increment x. You probably meant this?
while (sqrt(c)!=int(sqrt(c))):
x=x+1
c = x**2+n # <--- UPDATE c

Type error Python programming

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.

Categories

Resources