I have this working code for finding eulerian cycle:
def eulerianCycle(node, graph):
cycle = [node]
for ih in range(len(graph)):
if graph[ih][node] == 1:
graph[node][ih] = 0
graph[ih][node] = 0
cycle = cycle[:1] + eulerianCycle(ih, graph) + cycle[1:]
return cycle
I want to convert it to iteration, but i cant figuire out how to do it.
My attempt
def eulerianCycle(node, graph):
stack = [node]
st = []
while len(stack) > 0:
node = stack.pop()
for ih in range(len(graph)):
if graph[ih][node] == 1:
graph[node][ih] = 0
graph[ih][node] = 0
stack.append(ih)
st.append(ih)
cycle = []
while len(st) > 0:
e = [st.pop()]
cycle = cycle[:1] + e + cycle[1:]
return cycle
Related
Whenever k = 2, the code runs in a loop
if k > 2 it sets all, but one of the centroids location to 0,0
I've reviewed it a couple of times , and it doesn't seem like there are any errors probably some sort of logic flaw. The code starts by having a class and its methods which initiate the centroids, calculate the Euclidean distance, and reassign centroids to the average positions of the points that are in the cluster. It then runs a loop that consists of reassigning and calculating distance until a list of the assignments are equal and then plots it.
class Kmeans:
def __init__(self, K, dataset, centroids, sorting):
self.K = K
self.dataset = dataset
self.centroids = centroids
self.sorting = sorting
#sets starting position of centroids
def initializeCentroids(self):
bigX = 0
bigY = 0
self.centroids = []
for i in self.dataset:
if i[0] > bigX:
bigX = i[0]
if i[1] > bigY:
bigY = i[1]
for q in range(self.K):
self.centroids.append([random.randint(0, bigX), random.randint(0, bigY)])
plt.scatter((self.centroids[0][0], self.centroids[1][0]), (self.centroids[0][1], self.centroids[1][1]))
return self.centroids
#calculates euclidean distance
def calcDistance(self):
self.sorting = []
for w in self.dataset:
print(w)
distances = []
counter = 0
for centr in self.centroids:
distances.append(math.sqrt(abs((centr[0] - w[0] * centr[0] - w[0]) + (centr[1] - w[1] * centr[1] - w[1]))))
counter += 1
if counter > 0:
try:
if distances[0] > distances[1]:
distances.pop(0)
if distances[1] > distances[0]:
distances.pop(1)
counter -= 1
except IndexError:
pass
self.sorting.append([w, counter, distances[0]])
return self.sorting
def reassignCentroids(self):
counter3 = 1
for r in range(len(self.centroids)):
positionsX = []
positionsY = []
for t in self.sorting:
if t[1] == counter3:
positionsX.append(t[0][0])
positionsY.append(t[0][1])
population = len(positionsY)
if population == 0:
population = 1
self.centroids.append([sum(positionsX) / population, sum(positionsY) / population])
counter3 += 1
self.centroids.pop(0)
return
k = 4
dataSetSize = input("Enter the amount of tuples you want generated: ")
data_set = []
for o in range(int(dataSetSize)):
data_set.append((random.randint(0, 1000), random.randint(0, 1000)))
attempt = Kmeans(k, data_set, 0, 0)
attempt.initializeCentroids()
xvals = []
yvals = []
sortCompare = []
# plots
for p in data_set:
xvals.append(p[0])
yvals.append(p[1])
running = True
while running:
if len(sortCompare) > 1:
centroidChoice0 = []
centroidChoice1 = []
for p in sortCompare[0]:
centroidChoice0.append(p[1])
for d in sortCompare[1]:
centroidChoice1.append(d[1])
print(centroidChoice1)
print(attempt.centroids)
if centroidChoice1 == centroidChoice0:
running = False
for m in attempt.centroids:
plt.scatter((attempt.centroids[0][0], attempt.centroids[1][0]), (attempt.centroids[0][1], attempt.centroids[1][1]))
running = False
sortCompare.pop(0)
attempt.calcDistance()
sortCompare.append(attempt.sorting)
attempt.reassignCentroids()
This is my code:
class solution:
lot = [[1,0,0], [1,0,0], [1,9,1]]
def move(lot):
if lot is None:
return -1
if (len(lot) <= 0 or len(lot[0]) <= 0):
return -1
q = []
visited = [len(lot)], [len(lot[0])]
direction= [(0,1), (0,-1), (1,0), (-1,0)]
q.append((0,0))
result = 0
while (len(q) > 0):
size = len(q)
for i in range(size):
node= q.pop(0)
x = node[0]
y = node[1]
visited[x][y]= True
if(lot[x][y] == 9):
return result
for dir in direction:
nx = x+ dir[0]
ny = y + dir[1]
r= len(lot[nx])
if (nx < 0 or nx >= len(lot) or ny < 0 or ny > r or lot[nx][ny] == 0 or visited[nx][ny] == True):
continue
q.append((nx,ny))
result += result
return result
print(move(lot))
It generates the following error:
File "prog.py", line 29, in move
if (nx < 0 or nx >= len(lot) or ny < 0 or ny > r or lot[nx][ny] == 0 or visited[nx][ny] == True):
IndexError: tuple index out of range
Your error is because of your visited variable. You're trying to access visited[nx][ny] which doesn't exist.
Separately, your DFS algorithm is incorrect. See here for how to implement DFS correctly.
Your function should be like this:
def move(lot):
if lot is None:
return -1
if (len(lot) <= 0 or len(lot[0]) <= 0):
return -1
q = []
visited = set()
q.append((0,0))
result = 0
while len(q)>0:
x,y = q.pop(0)
if(lot[x][y]==9):
return result
if (x,y) in visited:
continue
visited.add((x,y))
for d in [(0,1), (0,-1), (1,0), (-1,0)]:
nx = x + d[0]
ny = y + d[1]
if (nx<0 or nx>=len(lot) or ny<0 or ny>len(lot[0]) or lot[nx][ny]==0 or (nx,ny) in visited):
continue
q.append((nx,ny))
result += 1
return result
I'm VERY new to Python (self learning) and am writing some code, and have read as much as possible (both on this website and youtube) to figure it out, and I'm perplexed as to why it's not working for me
I've generated this dictionary of dictionaries (may not be most efficient, please let me know how to improve, been doing this a couple weeks only):
graphx = []
all_locs = []
def graph(width, height):
for r in range(height):
row = []
for c in range(width):
t = (r, c)
row.append(t)
all_locs.append(t)
graphx.append(row)
graph(width, height)
# # Builds a dictionary of all nodes, and their weight
weighted_grid = {}
for node in graphx:
for c in node:
n = {}
s = {}
e = {}
w = {}
if (c[0] < height) and (c[0] > 0):
n[c[0] + 1, c[1]] = 1
s[c[0] - 1, c[1]] = 1
elif c[0] == 0:
n[c[0] + 1, c[1]] = 1
elif c[0] == height:
s[c[0] - 1, c[1]] = 1
if c[1] < width and c[1] > 0:
e[c[0], c[1] + 1] = 1
w[c[0], c[1] - 1] = 1
elif c[1] == 0:
e[c[0], c[1] + 1] = 1
elif c[1] == height:
w[c[0], c[1] - 1] = 1
temp = {}
blank = {}
if n != blank:
temp[c[0] + 1, c[1]] = 1
if e != blank:
temp[c[0], c[1] + 1] = 1
if s != blank:
temp[c[0] - 1, c[1]] = 1
if w != blank:
temp[c[0], c[1] - 1] = 1
weighted_grid[c[0],c[1]] = temp
When I run dijikstras, using the the tuples as start and destination, I get an error. Here's the version of dijkstras I'm running:
def dijkstra(graph, start, goal):
shortest_distance = {} # records the current cost to reach that node.
track_predecessor = {} # keeps track of the path that led to this node.
unseen_nodes = graph # Iterate through the graph to check all nodes.
infinity = 99999 # Make it any large number,greater than possible path weights.
track_path = [] # gives us the trace-back path of the optimal route
for node in unseen_nodes:
shortest_distance[node] = infinity
shortest_distance[start] = 0
while unseen_nodes:
min_distance_node = None
for node in unseen_nodes:
if min_distance_node is None:
min_distance_node = node
elif shortest_distance[node] < shortest_distance[min_distance_node]:
min_distance_node = node
path_options = graph[min_distance_node].items()
for child_node, weight in path_options:
if weight + shortest_distance[min_distance_node] < shortest_distance[child_node]:
shortest_distance[child_node] = weight + shortest_distance[min_distance_node]
track_predecessor[child_node] = min_distance_node
unseen_nodes.pop(min_distance_node)
current_node = goal
while current_node != start:
try:
track_path.insert(0, current_node)
current_node = track_predecessor[current_node]
except KeyError:
break
track_path.insert(0, start)
if shortest_distance[goal] != infinity:
pass
The error I get is:
Traceback (most recent call last):
File "C:/Users/Dave/Desktop/Important/PycharmProjects/DMT2/dungeonmasterstome/Main.py", line 318, in <module>
dijkstra(weighted_grid, (0, 0), (0,1))
File "C:/Users/Dave/Desktop/Important/PycharmProjects/DMT2/dungeonmasterstome/Main.py", line 300, in dijkstra
if weight + shortest_distance[min_distance_node] < shortest_distance[child_node]:
KeyError: (0, 30)
Thoughts and thanks for any help and constructive criticism.
I just create benchmark to compare speed of two implementation of Quick sort.
Iterative and recursion.
I expected than recursive will be slower, but I got that plot (blue is rec):
It's possible that recursion is faster? Maybe I just do some mistake in my code?
Just in case I pase my code.
import time
import random
import sys
arrayList = []
arr = [random.randint(1,15000) for _ in range(1000)]
numbersList = [100000, 300000, 500000, 900000, 1000000, 1500000]
numbersForBenchmark = []
for i in range(len(numbersList)):
arr = [random.randint(1,15000) for _ in range(numbersList[i])]
numbersForBenchmark.append(arr)
print(numbersForBenchmark)
recursionTimeArray = []
iterationTimeArray = []
arrRe = arr
arrIt = arr
def partition(lst, start, end):
pos = start
for i in range(start, end):
if lst[i] < lst[end]: # in your version it always goes from 0
lst[i],lst[pos] = lst[pos],lst[i]
pos += 1
lst[pos],lst[end] = lst[end],lst[pos] # you forgot to put the pivot
# back in its place
return pos
def quick_sort_recursive(lst, start, end):
if start < end: # this is enough to end recursion
pos = partition(lst, start, end)
quick_sort_recursive(lst, start, pos - 1)
quick_sort_recursive(lst, pos + 1, end)
#print(lst)
def iter(arr,l,h):
i = ( l - 1 )
x = arr[h]
for j in range(l , h):
if arr[j] <= x:
# increment index of smaller element
i = i+1
arr[i],arr[j] = arr[j],arr[i]
arr[i+1],arr[h] = arr[h],arr[i+1]
return (i+1)
def quickSortIterative(arr,l,h):
size = h - l + 1
stack = [0] * (size)
top = -1
top = top + 1
stack[top] = l
top = top + 1
stack[top] = h
while top >= 0:
# Pop h and l
h = stack[top]
top = top - 1
l = stack[top]
top = top - 1
p = iter( arr, l, h )
if p-1 > l:
top = top + 1
stack[top] = l
top = top + 1
stack[top] = p - 1
if p+1 < h:
top = top + 1
stack[top] = p + 1
top = top + 1
stack[top] = h
for i in range(len(numbersForBenchmark)):
arrRe = numbersForBenchmark[i][:]
arrIt = numbersForBenchmark[i][:]
n = len(arrIt)
start = time.time()
quickSortIterative(arrIt, 0, n-1)
end = time.time()
ITime = end - start
iterationTimeArray.append(ITime)
try:
n = len(arrRe)
start = time.time()
quick_sort_recursive(arrRe,0,n-1)
end = time.time()
rekTime = end - start
recursionTimeArray.append(rekTime)
except RecursionError as re:
print('Sorry but this maze solver was not able to finish '
'analyzing the maze: {}'.format(re.args[0]))
print("REK time", recursionTimeArray)
print("ITER TIME", iterationTimeArray)
# evenly sampled time at 200ms intervals
import matplotlib.pyplot as plt
plt.plot([10,100,500,1000,5000,8000 ], recursionTimeArray,[10,100,500,1000,5000,8000], iterationTimeArray)
plt.show()
The plots look OK, but I expected a completely different result. Hence my doubts about the results.
I have converted the code given at this link into a python version. The code is supposed to calculate the correct value of maximum value to be filled in knapsack of weight W. I have attached the code below:
#http://www.geeksforgeeks.org/branch-and-bound-set-2-implementation-of-01-knapsack/
from queue import Queue
class Node:
def __init__(self):
self.level = None
self.profit = None
self.bound = None
self.weight = None
def __str__(self):
return "Level: %s Profit: %s Bound: %s Weight: %s" % (self.level, self.profit, self.bound, self.weight)
def bound(node, n, W, items):
if(node.weight >= W):
return 0
profit_bound = int(node.profit)
j = node.level + 1
totweight = int(node.weight)
while ((j < n) and (totweight + items[j].weight) <= W):
totweight += items[j].weight
profit_bound += items[j].value
j += 1
if(j < n):
profit_bound += (W - totweight) * items[j].value / float(items[j].weight)
return profit_bound
Q = Queue()
def KnapSackBranchNBound(weight, items, total_items):
items = sorted(items, key=lambda x: x.value/float(x.weight), reverse=True)
u = Node()
v = Node()
u.level = -1
u.profit = 0
u.weight = 0
Q.put(u)
maxProfit = 0;
while not Q.empty():
u = Q.get()
if u.level == -1:
v.level = 0
if u.level == total_items - 1:
continue
v.level = u.level + 1
v.weight = u.weight + items[v.level].weight
v.profit = u.profit + items[v.level].value
if (v.weight <= weight and v.profit > maxProfit):
maxProfit = v.profit;
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
Q.put(v)
v.weight = u.weight
v.profit = u.profit
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
# print items[v.level]
Q.put(v)
return maxProfit
if __name__ == "__main__":
from collections import namedtuple
Item = namedtuple("Item", ['index', 'value', 'weight'])
input_data = open("test.data").read()
lines = input_data.split('\n')
firstLine = lines[0].split()
item_count = int(firstLine[0])
capacity = int(firstLine[1])
print "running from main"
items = []
for i in range(1, item_count+1):
line = lines[i]
parts = line.split()
items.append(Item(i-1, int(parts[0]), float(parts[1])))
kbb = KnapSackBranchNBound(capacity, items, item_count)
print kbb
The program is supposed to calculate value of 235 for following items inside file test.data:
5 10
40 2
50 3.14
100 1.98
95 5
30 3
The first line shows number of items and knapsack weight. Lines below first line shows the value and weight of those items. Items are made using a namedtuple and sorted according to value/weight. For this problem I am getting 135 instead of 235. What am I doing wrong here?
EDIT:
I have solved the problem of finding correct items based on branch and bound. If needed, one can check it here
The problem is that you're inserting multiple references to the same Node() object into your queue. The fix is to initialize two new v objects in each iteration of the while-loop as follows:
while not Q.empty():
u = Q.get()
v = Node() # Added line
if u.level == -1:
v.level = 0
if u.level == total_items - 1:
continue
v.level = u.level + 1
v.weight = u.weight + items[v.level].weight
v.profit = u.profit + items[v.level].value
if (v.weight <= weight and v.profit > maxProfit):
maxProfit = v.profit;
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
Q.put(v)
v = Node() # Added line
v.level = u.level + 1 # Added line
v.weight = u.weight
v.profit = u.profit
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
# print(items[v.level])
Q.put(v)
Without these reinitializations, you're modifying the v object that you already inserted into the queue.
This is different from C++ where the Node objects are values that are implicitly copied into the queue to avoid aliasing problems such as these.