Dijsktra's Shortest Path Algorithm - python

When I run this, the end output is a table with columns:
Vertex - DisVal - PrevVal - Known.
The two nodes connected to my beginning node show the correct values, but none of the others end up getting updated. I can include the full program code if anyone wants to see, but I know the problem is isolated here. I think it may have to do with not changing the index the right way. This is a simple dijsktra's btw, not the heap/Q version.
Here's the rest of the code: http://ideone.com/UUOUn8
The adjList looks like this: [1: 2, 4, 2: 6, 3, ...] where it shows each node connected to a vertex. DV = distance value (weight), PV = previous value (node), known = has it bee visited
def dijkstras(graph, adjList):
pv = [None] * len(graph.nodes)
dv = [999]*len(graph.nodes)
known = [False] * len(graph.nodes)
smallestV = 9999
index = 0
dv[0] = 0
known[0] = True
for i in xrange(len(dv)):
if dv[i] < smallestV and known[i]:
smallestV = dv[i]
index = i
known[index] = True
print smallestV
print index
for edge in adjList[index]:
if (dv[index]+graph.weights[(index, edge)] < dv[edge]):
dv[edge] = dv[index] + graph.weights[(index, edge)]
pv[edge] = index
printTable(dv, pv, known)

The first iteration sets smallestV and index to 0 unconditionally, and they never change afterwards (assuming non-negative weights).
Hard to tell what you are trying to do here.

Related

Identify overlap sequence

I have a question, I am building a program where I want to identify the overlapped sequence of two lists.
sequ_1 = 'blablablaaaabla'
seque_2 = 'aaablaccbla'
The expected output would be: 'aaabla'
I created this function that would tell me whether or not the sequence from the sequ_2 overlaps with sequ_1:
` def overlap (sequ_1, sequ_2):
count_overlapp = 0
count_nooverlapp = 0
for i in range(len(sequ_1)-len(sequ_2)+1):
if loci1[i:i+len(sequ_1)]==sequ_2:
count_overlapp= count_overlapp+1
else: count_nooverlapp = count_nooverlapp +1
return print(f'The number of overlapped sequence:{count_overlapp}\nThe number of not overlapped sequence:{count_nooverlapp}')`
But it only computes well if the sequ_2 is within sequ_1, but it doesnt if sequ_2 is partially overlaps sequ_1
What would be great is to identify the sequence that overlapps as well
Thank you very much in advance
maybe this solution is that you need:
sequ_1 = 'blablablaaaabla'
seque_2 = 'aaablaccbla'
overlap = ""
for i in range(len(seque_2)):
for j in range(i + 1, len(seque_2)):
tmp = seque_2[i:j+1]
if len(tmp) > len(overlap) and tmp in sequ_1:
overlap = tmp
print(overlap)
Output: aaabla

Code is executing process that should have been denied in the initial statement and i dont know why

so i have a data set that contains data similar to: (Left:date, Middle: value, Right:time difference between dates).
I am developing a code that will scan this data set and if the first value in the right column is bigger than 1 and the successive ones are less than 1, then get me the max value(middle) and tell me the date it happened and put those in a new list. So in the above example, it should check the first 5 rows, find the max value to be 13.15 and tell me the date it happened and store it in a new list. However, my code is not doing this, in fact sometimes is actually produces duplicates and im having trouble finding out why. Code is below:
list_final_multiple = []
for i in range(0,len(file_dates_list)): #gets all of the rest of the data
n = 1
if (file_gap_list[i] > 1 or i == 0) and file_gap_list[i+n] <= 1:
while ((i + n) < len(file_dates_list)) and (file_gap_list[i + n] <= 1):
n = n + 1
max_value = (max(file_hs_list[i:i + n]))
max_value_location = file_hs_list.index(max_value)
list_final_multiple.append([file_dates_list[max_value_location], file_hs_list[max_value_location]])
any help would be appreciated.

Create "synthetic points"

I need to create inside a python routine, something that I am calling "synthetic points".
I have a series of data which vary between -1 and 1, however, when I put this data on a chart, they form a trapezoidal chart.
What I would like to do is create points where the same x-axis value, could take two y-axis values, and then, this will create a chart with
straight lines making a "rectangular chart"
An example the format data that I have:
0;-1
1;-1
2;-1
3;-1
4;-1
5;-1
6;-1
7;1
8;1
9;1
10;1
11;1
12;1
13;1
14;1
15;1
16;-1
17;-1
18;-1
19;-1
20;-1
For example, in this case, I would need the data assume the following format:
0;-1
1;-1
2;-1
3;-1
4;-1
5;-1
6;-1
6;1 (point 6 with two values)
7;1
8;1
9;1
10;1
11;1
12;1
13;1
14;1
15;1
15;-1 (point 15 with two values)
16;-1
17;-1
18;-1
19;-1
20;-1
So what you need to do is, always when I had a value change, this will create a new point. This makes the graph, rectangular, as the only possible values for the y variable are -1 and 1.
The code I need to enter is below. What was done next was just to put the input data in this format of -1 and 1.
arq = open('vazdif.out', 'rt')
list = []
i = 0
for row in arq:
field = row.split(';')
vaz = float(field[2])
if vaz < 0:
list.append("-1")
elif vaz > 0:
list.append("1")
n = len(list)
fou = open('res_id.out','wt')
for i in range(n):
fou.write('{};{}\n'.format(i,list[i]))
fou.close
Thank you for your help
P.s. English is not my first language, forgive my mistakes on write or on the code.
I added a new value prev_value, if the previous value is of the opposite sign (multiply with the current value < 0), it adds an extra index to the list.
I think the field[1] and field[2] are probably wrong, but I'll trust your code works so far. Similar with fou, I would replace with with open ...
arq = open('vazdif.out', 'rt')
list = []
i = 0
prev_value = 0
for row in arq:
field = row.split(';')
xxx = int(field[1])
vaz = float(field[2])
if vaz * prev_value < 0:
list.append([list[-1][0], - list[-1][1]])
if vaz < 0:
list.append([xxx, -1])
else:
list.append([xxx, 1])
prev_val = vaz
fou = open('res_id.out','wt')
for i in list:
fou.write(f'{i[0]};{i[1]}\n')
fou.close

8 puzzle using blind search (brute-force) and manhattan distance heuristic

I developed my own program in Python for solving 8-puzzle. Initially I used "blind" or uninformed search (basically brute-forcing) generating and exploring all possible successors and using breadth-first search. When it finds the "goal" state, it basically back-tracks to the initial state and delivers (what I believe) is the most optimized steps to solve it. Of course, there were initial states where the search would take a lot of time and generate over 100,000 states before finding the goal.
Then I added the heuristic - Manhattan Distance. The solutions started coming exponentially quickly and with lot less explored states. But my confusion is that some of the times, the optimized sequence generated was longer than the one reached using blind or uninformed search.
What I am doing is basically this:
For each state, look for all possible moves (up, down, left and right), and generate the successor states.
Check if state is repeat. If yes, then ignore it.
Calculate Manhattan for the state.
Pick out the successor(s) with lowest Manhattan and add at the end of the list.
Check if goal state. If yes, break the loop.
I am not sure whether this would qualify as greedy-first, or A*.
My question is, is this an inherent flaw in the Manhattan Distance Heuristic that sometimes it would not give the most optimal solution or am i doing something wrong.
Below is the code. I apologize that it is not a very clean code but being mostly sequential it should be simple to understand. I also apologize for a long code - I know I need to optimize it. Would also appreciate any suggestions/guidance for cleaning up the code. Here is what it is:
import numpy as np
from copy import deepcopy
import sys
# calculate Manhattan distance for each digit as per goal
def mhd(s, g):
m = abs(s // 3 - g // 3) + abs(s % 3 - g % 3)
return sum(m[1:])
# assign each digit the coordinate to calculate Manhattan distance
def coor(s):
c = np.array(range(9))
for x, y in enumerate(s):
c[y] = x
return c
#################################################
def main():
goal = np.array( [1, 2, 3, 4, 5, 6, 7, 8, 0] )
rel = np.array([-1])
mov = np.array([' '])
string = '102468735'
inf = 'B'
pos = 0
yes = 0
goalc = coor(goal)
puzzle = np.array([int(k) for k in string]).reshape(1, 9)
rnk = np.array([mhd(coor(puzzle[0]), goalc)])
while True:
loc = np.where(puzzle[pos] == 0) # locate '0' (blank) on the board
loc = int(loc[0])
child = np.array([], int).reshape(-1, 9)
cmove = []
crank = []
# generate successors on possible moves - new states no repeats
if loc > 2: # if 'up' move is possible
succ = deepcopy(puzzle[pos])
succ[loc], succ[loc - 3] = succ[loc - 3], succ[loc]
if ~(np.all(puzzle == succ, 1)).any(): # repeat state?
child = np.append(child, [succ], 0)
cmove.append('up')
crank.append(mhd(coor(succ), goalc)) # manhattan distance
if loc < 6: # if 'down' move is possible
succ = deepcopy(puzzle[pos])
succ[loc], succ[loc + 3] = succ[loc + 3], succ[loc]
if ~(np.all(puzzle == succ, 1)).any(): # repeat state?
child = np.append(child, [succ], 0)
cmove.append('down')
crank.append(mhd(coor(succ), goalc))
if loc % 3 != 0: # if 'left' move is possible
succ = deepcopy(puzzle[pos])
succ[loc], succ[loc - 1] = succ[loc - 1], succ[loc]
if ~(np.all(puzzle == succ, 1)).any(): # repeat state?
child = np.append(child, [succ], 0)
cmove.append('left')
crank.append(mhd(coor(succ), goalc))
if loc % 3 != 2: # if 'right' move is possible
succ = deepcopy(puzzle[pos])
succ[loc], succ[loc + 1] = succ[loc + 1], succ[loc]
if ~(np.all(puzzle == succ, 1)).any(): # repeat state?
child = np.append(child, [succ], 0)
cmove.append('right')
crank.append(mhd(coor(succ), goalc))
for s in range(len(child)):
if (inf in 'Ii' and crank[s] == min(crank)) \
or (inf in 'Bb'):
puzzle = np.append(puzzle, [child[s]], 0)
rel = np.append(rel, pos)
mov = np.append(mov, cmove[s])
rnk = np.append(rnk, crank[s])
if np.array_equal(child[s], goal):
print()
print('Goal achieved!. Successors generated:', len(puzzle) - 1)
yes = 1
break
if yes == 1:
break
pos += 1
# generate optimized steps by back-tracking the steps to the initial state
optimal = np.array([], int).reshape(-1, 9)
last = len(puzzle) - 1
optmov = []
rank = []
while last != -1:
optimal = np.insert(optimal, 0, puzzle[last], 0)
optmov.insert(0, mov[last])
rank.insert(0, rnk[last])
last = int(rel[last])
# show optimized steps
optimal = optimal.reshape(-1, 3, 3)
print('Total optimized steps:', len(optimal) - 1)
print()
for s in range(len(optimal)):
print('Move:', optmov[s])
print(optimal[s])
print('Manhattan Distance:', rank[s])
print()
print()
################################################################
# Main Program
if __name__ == '__main__':
main()
Here are some of the initial states and the optimized steps calculated if you would like to check (above code would give this option to choose between blind vs Informed search)
Initial states
- 283164507 Blind: 19 Manhattan: 21
- 243780615 Blind: 15 Manhattan: 21
- 102468735 Blind: 11 Manhattan: 17
- 481520763 Blind: 13 Manhattan: 23
- 723156480 Blind: 16 Manhattan: 20
I have deliberately chosen examples where results would be quick (within seconds or few minutes).
Your help and guidance would be much appreciated.
Edit: I have made some quick changes and managed to reduce some 30+ lines. Unfortunately can't do much at this time.
Note: I have hardcoded the initial state and the blind vs informed choice. Please change the value of variable "string" for initial state and the variable "inf" [I/B] for Informed/Blind. Thanks!

Finding the ancestral nodes of a tree created with a simple geometric progression

I'm looking for an algorithm that will give me the ancestral line for any node in any tree that has been created using a geometric series where a = 1, and r equals any whole number. For example the tree in the image below, r = 2, and the ancestral line for 26 is [26, 13, 6, 3, 1].
I've had a go at this myself and have come up with an answer that appears to give me the correct answer for the values of r that I've tried. But before I create an app that uses this algorithm to provide file-system resources I want to be sure that I'm not missing some edge-case somewhere. It feels like the kind of problem that must have an established solution that is almost certainly more elegant that mine. Does anyone know of anything?
# My python implementation.
import math
def findLevelOfFolder(folder):
""" Find the 'level' on which a given folder sits. """
if folder == 1:
return 1
else:
level = 2
while True:
lower, upper= boundsOfLevel(level)
if folder >= lower and folder <= upper:
return level
level += 1
def sumOfProgression(r, upToAndIncludingTerm):
"""
Sums a simple geometric series.
If r = 2, and upToAndIncludingTerm = 6, we'refinding the value of...
pow(2, 0) + pow(2, 1) + pow(2, 3) + ... + pow(2, 5)
"""
rRepeated = [r] * upToAndIncludingTerm
powers = range(0, upToAndIncludingTerm)
return sum(map(pow, rRepeated, powers))
def boundsOfLevel(level):
"""
A levels 'bounds' refers to the number of the first folder and the last folder
on that level. For example, when r == 2, and the level == 3, the
bounds is (4, 7). The smallest possible level is 1, which, for any
value of r always returns (1, 1).
"""
assert(level > 0, "Smallest possible level is 1.")
if level == 1:
return 1, 1
else:
lower = sumOfProgression(foldersPerFolder, level-1) + 1
upper = lower + pow(foldersPerFolder, level-1) - 1
return lower, upper
def ancestorsOfFolder(folder, ancestors):
""" Find the shortest route from folder '1' for the specified folder value.
On completion, ancestors will contain a list of numbers each of which
represents a folder in the ancestral line of 'folder'. The first number in
the list will always be 'folder' and the last number will always be 1."""
# First get the level...
level = findLevelOfFolder(folder)
lowerBoundOfPreviousLevel, _ = boundsOfLevel(level-1)
relativePosition = folder - sumOfProgression(foldersPerFolder, level-1)
parent = (lowerBoundOfPreviousLevel - 1) + math.ceil(relativePosition/foldersPerFolder)
ancestors.append(parent)
if parent != 1:
ancestorsOfFolder(parent, ancestors)
# 'r' value
foldersPerFolder = 2
# looking for ancestral line of...
folder = 23
print(ancestorsOfFolder(folder, [folder])) # -> [23, 11, 5, 2, 1]
The pattern is easier to see if you start by numbering the root as 0.
For r = 4:
0
1 2 3 4
5..8 9..12 13..16 17..20
In this case, each node k would have floor((k-1)/r) as its parent.
If you start the numbering at 1, though, as in
1
2 3 4 5
6..9 10..13 14..17 18..21
it gets a little messier. You need to subtract something before dividing by 4, then add something else back. What those somethings are is not immediately clear to me. My advice: work with a 0-based tree if possible :)
Third time's the charm (third edit, anyway).
The parent at each level can be found with the equation folder = (folder - 2) // r + 1:
def ancestorsOfFolder(folder, r):
ancestors = []
while folder > 0:
ancestors.append(folder)
folder = (folder - 2) // r + 1
return ancestors
EDIT: I agree, using a zero-based tree is preferable. The parents can be found with the equation folder = (folder - 1) // r. Here is the code:
def ancestorsOfFolder(folder, r):
ancestors = []
while folder > 0:
ancestors.append(folder)
folder = (folder - 1) // r
ancestors.append(0)
return ancestors

Categories