Is there a code to define / sort through lists?
Advanced solution
You can use the min function of python with the key argument like this:
def find_closest(start_point, remaining_points):
return min(remaining_points, key=lambda a: distance(start_point, a))
Basic solution
Because of your specific needs (only loops and if statements), here is another solution. For other people who are not restricted, I recommend using the above solution.
def find_closest(start_point, remaining_points):
closest = None
closest_distance = 1000000
# Better but more advanced initialisation
# closest_distance = float("inf")
for element in list(remaining_points):
dist = distance(start_point, element)
if dist < closest_distance:
closest = element
closest_distance = dist
return closest
Explanation
Before going through all points, we initialise the closest point to None (it is not found yet) and the closest_distante to a very high value (to be sure that the first evaluated point will be closer).
Then, for each point in remaining_points, we calculate its distance from start_point and store it in dist.
If this distance dist is less than closest_distance, then the current point is closest from the current stored one, so we update the stored closest point closest with the current point and we update the closest_distance with the current distance dist.
When all points have been evaluated, we return the closest point closest.
Links for more information
min function: https://www.programiz.com/python-programming/methods/built-in/min
lambda function: https://www.w3schools.com/python/python_lambda.asp
A quick and straightforward solution would be to create a list of results and then corroborate the index with your list of remaining points (because they are inherently lined up). Below is a step-by-step process to achieving this, and at the very bottom is a cleaned-up version of the code.
def find_closest(start_point, remaining_points):
results = [] # list of results for later use
for element in list(remaining_points):
result = distance(start_point, element)
results.append(result) # append the result to the list
# After iteration is finished, find the lowest result
lowest_result = min(results)
# Find the index of the lowest result
lowest_result_index = results.index(lowest_result)
# Corroborate this with the inputs
closest_point = remaining_points[lowest_result_index]
# Return the closest point
return closest_point
Or to simplify the code:
def find_closest(start_point, remaining_points):
results = []
for element in remaining_points:
results.append(distance(start_point, element))
return remaining_points[results.index(min(results))]
Edit: you commented saying you can't use Python's in-built min() function. A solution would be to just create your own functional minimum_value() function.
def minimum_value(lst: list):
min_val = lst[0]
for item in lst:
if item < min_val:
min_val = item
return min_val
def find_closest(start_point, remaining_points):
results = []
for element in remaining_points:
results.append(distance(start_point, element))
return remaining_points[results.index(minimum_value(results))]
Related
I am trying to find the nearest points on an x,y plane within given radius using kd trees. I mapped all the points in the tree, but the problem arise since the points I am providing to the algorithm to search for the nearest point are themself mapped in the tree. In other words, I'm getting the same point in return so the distance is basically 0. So I should be looking for the second nearest point I guess. The way I thought it might be achievable was doing the same thing but getting the result that was worst than the best_result but better than the root. I have been trying to implement this but have been unsuccessful so far. I did this with nested for loops its way easier with for loops to get the second-best result.
here's my kd tree implementation:
def kdtree(points, depth = 0 ):
n = len(points)
if n<=0:
return None
axis = depth % k
sorted_points = sorted(points, key = lambda point: point[axis])
if n % 2 == 0:
median_idx = int(n/2)
else:
median_idx = floor(n/2)
return{
'point': sorted_points[median_idx],
'left': kdtree(sorted_points[:median_idx], depth+1),
'right': kdtree(sorted_points[median_idx+1:], depth+1)
}
Here is my function for searching the nearest point
kd_nearest_search (root, point, depth = 0):
if root is None:
return None
axis = depth % k
apposite_branch = None
if point[axis] < root['point'][axis]:
next_branch = root['left']
opposite_branch = root['right']
else:
next_branch = root['right']
opposite_branch = root['left']
best_result = best_distance(point,kdtree_closest_point(next_branch,point,depth+1), root['point'])
if distance(point,best_result) > (abs(point[axis] - root['point'][axis])):
best_result = best_distance(point,kdtree_closest_point(next_branch,point,depth+1), best_result)
return best_result
I don't know your kd implementation. But I'll give you the basic idea.
Create tuples of (min_possible_distance, type, object) where the distance is the minimum possible distance to your searched for point the type can be either "box" or "point", and the object is whatever the thing is.
Put those tuples into a heap.
And now, in pseudocode, you do this:
place (0, "box", root_of_tree) into new heap
while heap is not empty:
(distance, type, obj) = pop minimal element from heap.
if type == "point":
yield obj
else:
if obj has a point:
store (distance, "point", point) in heap
for child_box from obj:
store (min_distance", "box", child_box) in heap
This will yield points in the kd tree, from closest to farthest. So you can just search until you find the second one. But alternately you could ask for the 10 nearest and it would give you that instead.
I have two arrays centroids and nodes
I need to find the shortest distance of each point in centroids to any point in nodes
The output for centroids is following
array([[12.52512263, 55.78940022],
[12.52027731, 55.7893347 ],
[12.51987146, 55.78855611]])
The output for nodes is following
array([[12.5217378, 55.7799275],
[12.5122589, 55.7811443],
[12.5241664, 55.7843297],
[12.5189395, 55.7802709]])
I use the following code to get the shortest distance
shortdist_from_centroid_to_node = np.min(cdist(centroids,nodes))
However, this is the output I get (I should get 3 lines of output)
Out[131]: 3.0575613850140956e-05
Can anyone specify what the problem is here? Thanks.
When you doing np.min it return the minimal value of the 2d-array.
You want the minimum value for each centroids.
shortest_distance_to_centroid = [min(x) for x in cdist(centroids,nodes)]
To have the associate index one way would be to get the index of the corresponding value. Another is to write a custom min() function that also return the index (so you parse the list only once)
[(list(x).index(min(x)), min(x)) for x in cdist(centroids,nodes)] # the cast list() is needed because numpy array don't have index methods
solution with a custom function:
def my_min(x):
current_min = x[0]
current_index = [1]
for i, v in enumerate(x[1:]):
if v < current_min:
current_min = v
current_index = i + 1
return (current_index, current_min)
[my_min(x) for x in cdist(centroids,nodes)]
I guess what you need is just add an arg called axis, just like this:
shortdist_from_centroid_to_node = np.min(cdist(centroids,nodes), axis=1)
As for the meaning of the axis arg, you could refer to numpy.min. All in all you need minimum on each row rather than on the whole matrix.
If I am not wrong your code says you are trying to access the min value hence you are getting a single value. remove np.min() try:
shortdist_from_centroid_to_node = cdist(centroids,nodes)
I have an error function, and sum of all errors on self.array:
#'array' looks something like this [[x1,y1],[x2,y2],[x3,y3],...,[xn,yn]]
#'distances' is an array with same length as array with different int values in it
def calcError(self,n,X,Y): #calculate distance of nth member of array from given point
X,Y = float(X),float(Y)
arrX = float(self.array[n][0])
arrY = float(self.array[n][1])
e = 2.71828
eToThePower = e**(-1*self.distances[n])
distanceFromPoint=math.sqrt((arrX-X)**2+(arrY-Y)**2)
return float(eToThePower*(distanceFromPoint-self.distances[n])**2)
def sumFunction(self,X,Y):
res = 0.0
for i in range(len(self.array)):
res += self.calcError(i,X,Y)
return res
I have been looking for a way to find for which coordinates sumFunction return value is minimal. I have heard about scipy yet I am looking for a way to build that manualy. Gradient descent won't seem to work either since it is very hard to derive this sum function.
Thank you!
Did you try that create variable as a dictionary then append all iteration like this {self.calcError(i,X,Y)}:{i,X,Y}. If you return minimum the variable.keys then you can reach the coordinate from the min keys to value.
This is my own modification of the famous contiguous sum problem. Given an array in python of nested subarrays, how can one optimally return the subarray with the largest sum? I tried this O(n) implementation, which always gives me the last subarray, but I don't see why.
def maxsublist(arr):
curr = sum(arr[0])
ind = 0
for i,j in enumerate(arr):
if sum(j)>curr:
ind = i
return arr[ind]
maxsublist([[1,2],[4,5],[5,96,1],[1,2,3]])
returns [1,2,3].
***Note: I have a better version using Python's sorted function, but this feels a bit too much like cheating.
def maxsublist2(arr):
sortedlists = sorted(arr, key= lambda x: sum(i for i in x))
return sortedlists[-1]
This doesn't sound like the contiguous sum problem at all. This should be enough:
max(arr, key=sum)
The error in your code is simply that you forgot to update curr at the same time as ind.
You need to update curr when you find an array whose sum is greater than its current value:
if sum(j) > curr:
ind = i
curr = sum(j)
Btw, you might want to create some local variable to store sum(j) in order not to sum the same thing twice.
I am having a hard time modifying this code, I'm really new to python and I am trying to find the closest pair among the 10 input integers from a user. Here's my code so far and there is a syntax error...
a = [0,1,2,3,4,5,6,7,8,9]
a[0]=input()
a[1]=input()
a[2]=input()
a[3]=input()
a[4]=input()
a[5]=input()
a[6]=input()
a[7]=input()
a[8]=input()
a[9]=input()
a.sort()
b=sorted(set(a))
for item in enumerate(a):
for item1 in enumerate(b):
c = item - enumerate(b)
if c = item-1:
print item
print c
Thank,
Ai
Your code is causing exceptions because you're not handling the output of enumerate properly. Your item values are going to be (value, index) pairs, not single values, so there's no way to subtract them directly.
Here's another implementation, which may be something like what you were aiming for:
import itertools
def find_nearest_pair(lst):
min_pair = None
min_distance = float("inf")
for a, b in itertools.combinations(lst, 2): # generates all (a,b) pairs
distance = abs(a-b) # abs makes distance always non-negative
if distance < min_distance:
min_pair = (a,b)
min_distance = distance
return min_pair # you could return min_distance here too (or instead)
You could even compress it down further using the min function:
nearest_pair = min(itertools.combinations(lst, 2),
key=lambda item: abs(item[0]-item[1]))
Or if you just want the value:
nearest_pair_distance = min(abs(a-b) for a, b in itertools.combinations(lst, 2))
What are all these calls for enumerate for? That's for when you want to iterate through a collection and also keep a counter. You should remove all of them - but especially the one in the line c = item - enumerate(b) which makes absolutely no sense.
Once you've got it running, you should see you have a number of logic errors too, but I'll leave you to fix those yourself.