I recently started programming in Python (3.5) and I am trying to solve a simple Breadth first search problem in Python (see code)
import queue
import networkx as nx
def bfs(graph, start, target):
frontier = queue.Queue()
frontier.put(start)
explored = list()
while not frontier.empty():
state = frontier.get()
explored.append(state)
print(explored)
if state == target:
return 'success'
print(graph.neighbors(state))
for neighbor in graph.neighbors(state):
if neighbor not in explored:
frontier.put(state)
return 'Failure to find path'
The code returns an infinite loop where it seems that frontier.get() does not delete the item from the queue. This makes the while loop infinite, as the first value in the queue is always the start node defined in the function input. The variable state is in each while loop the same (always the start node).
What am I doing wrong? As from what I understood the queue should move from the start node to the neighbours of the start node and therefore a loop should not occur.
Two things. First, I assume everything from the while on down ought to be indented by one level.
If I'm reading your algorithm correctly, I believe the error is on the last line before the return. You have:
frontier.put(state)
which just inserts the node you were already looking at. I think what you should be doing instead is:
frontier.put(neighbor)
so that you explore all the immediate neighbors of state. Otherwise you just keep looking at the start node over and over.
Because you're putting the state value in the queue again. Change this:
for neighbor in graph.neighbors(state):
if neighbor not in explored:
frontier.put(state) # Here you put the 'state' back!
to this:
for neighbor in graph.neighbors(state):
if neighbor not in explored:
frontier.put(neighbor) # Put in the neighbours instead.
Related
I have this project in Theory of Computation course and have this function in DFA class where it basically determines whether a specific state is reachable from the start state or not (similar to checking connectivity in a simple graph). I have this for loop:
def is_reachable(self, dest_state):
reachable_states = [self.start_state]
for state in reachable_states:
for char in self.alphabet:
if self.transition_function[state][char] not in reachable_states:
reachable_states.append(self.transition_function[state][char])
return dest_state in reachable_states
My question is: Does the first for loop (parent for loop) reset every time something is added to the set or does it just keep going? Because if it resets every time then the time complexity of this function would not be very efficient.
My tree has the following structure:
tree={'0':('1','2','3'), '1':('4'), '2':('5','6'), '3':(), '4':('7','8'), '8':('9','10','11')}
How can I wrote Python code to retrieve all given child nodes of a particular node?
For example, if I give it node 4, the code should retrieve 7,8,9,10,11.
For node 2, it should retrieve 5, 6 and so on.
I just started learning the basics of Python but I have no idea how to implement this for non-binary trees..
You can use a queue. Once you've gotten the user's requested value, push it into the queue. Then, while the queue isn't empty, pop a value, print it, check the dict, and if the current value is a key in the dict, add each of those values to the queue to check them in the next pass.
import queue
tree={'0':('1','2','3'), '1':('4'), '2':('5','6'), '3':(), '4':('7','8'), '8':('9','10','11')}
num = input("what you want ")
q = queue.Queue()
q.put(num)
while not q.empty():
n = q.get()
for s in n:
print(s)
if s in tree:
q.put(tree[s])
Demo
Note that if you have a tree tree={'0':('1'), '1':('0')}, or any other circular reference, this code will run forever. Be careful!
I am relatively new to Python and I need some help. This is also my first post on this site. I am trying to change the value of the colorspace knob in Read Node I have labeled "Plate". I would like to use that value later on. Here is my code so far:
def LabelPlate():
n = nuke.thisNode()
if n != None:
label = n['label'].value()
n['label'].setValue('Plate')
def LabelLook():
name= "Plate"
for node in nuke.allNodes():
if name == node.knob("label").value():
return True
def LabelLookTwo():
name= "Plate"
for node in nuke.allNodes():
if name == node.knob("label").value():
return node.knob("name").value()
def PlateColorspaceSet():
n = LabelLookTwo()
if nuke.toNode("n")["colorspace"].value() == "default (sRGB)":
nuke.toNode("n")["colorspace"].setValue("sRGB")
def LabelQuestion():
if LabelLook() != True:
if nuke.ask('Is this Read your main Plate?'):
LabelPlate()
PlateColorspaceSet()
nuke.addOnUserCreate(LabelQuestion, nodeClass = 'Read')
So order of events:
Bring in Read node
Ask if Read node is your main plate
a. If yes, label node as "Plate", proceed to step 3
b. If no, bring in unlabeled Read node
Change colorspace in node labeled "Plate" from default to an actual value.
So far, I can get the first 2 steps to work. But on step 3, I get
"'NoneType' object has no attribute 'getitem'"
Any ideas why? Is there a better way to get the colorspace value?
I figured out the problem.
nuke.addOnUserCreate is where I was calling the function on the creation of the read node. Problem is, it runs the script before everything exists. So not everything works because not everything is there in Nuke yet, so things, like my variable n = LabelLookTwo(), return as None.
Using addOnCreate instead runs the script after the node and it's defaults have been set and created. So using this, the rest of the script runs exactly as originally written.
Where I found the answer
I need to try all possible paths, branching every time I hit a certain point. There are <128 possible paths for this problem, so no need to worry about exponential scaling.
I have a player that can take steps through a field. The player
takes a step, and on a step there could be an encounter.
There are two options when an encounter is found: i) Input 'B' or ii) Input 'G'.
I would like to try both and continue repeating this until the end of the field is reached. The end goal is to have tried all possibilities.
Here is the template, in Python, for what I am talking about (Step object returns the next step using next()):
from row_maker_inlined import Step
def main():
initial_stats = {'n':1,'step':250,'o':13,'i':113,'dng':0,'inp':'Empty'}
player = Step(initial_stats)
end_of_field = 128
# Walk until reaching an encounter:
while player.step['n'] < end_of_field:
player.next()
if player.step['enc']:
print 'An encounter has been reached.'
# Perform an input on an encounter step:
player.input = 'B'
# Make a branch of player?
# perform this on the branch:
# player.input = 'G'
# Keep doing this, and branching on each encounter, until the end is reached.
As you can see, the problem is rather simple. Just I have no idea, as a beginner programmer, how to solve such a problem.
I believe I may need to use recursion in order to keep branching. But I really just do not understand how one 'makes a branch' using recursion, or anything else.
What kind of solution should I be looking at?
You should be looking at search algorithms like breath first search (BFS) and depth first search (DFS).
Wikipedia has this as the pseudo-code implementation of BFS:
procedure BFS(G, v) is
let Q be a queue
Q.enqueue(v)
label v as discovered
while Q is not empty
v← Q.dequeue()
for all edges from v to w in G.adjacentEdges(v) do
if w is not labeled as discovered
Q.enqueue(w)
label w as discovered
Essentially, when you reach an "encounter" you want to add this point to your queue at the end. Then you pick your FIRST element off of the queue and explore it, putting all its children into the queue, and so on. It's a non-recursive solution that is simple enough to do what you want.
DFS is similar but instead of picking the FIRST element form the queue, you pick the last. This makes it so that you explore a single path all the way to a dead end before coming back to explore another.
Good luck!
I've been scouring the internet and haven't been able to find anything that would help. I'm running a basic dfs algorithm in python. My error is in the explore subroutine of dfs
def dfs(graph):
for node in graph:
if not node in visited:
explore(graph, node)
def explore(graph, v):
visited.append(v)
adjNode = graph[v]
for i in range(0, len(adjNode)):
if not adjNode[i] in visited:
explore(graph, adjNode[i])
visited is a list I'm using to keep track of visited nodes and graph is a dictionary that holds the graph.
With a standard recursion limit of 1000 I get this error
File "2breakDistance.py", line 45, in explore
explore(graph, adjNode[i], cycles)
File "2breakDistance.py", line 45, in explore
explore(graph, adjNode[i], cycles)
File "2breakDistance.py", line 45, in explore
explore(graph, adjNode[i], cycles)
File "2breakDistance.py", line 45, in explore
explore(graph, adjNode[i], cycles)
File "2breakDistance.py", line 41, in explore
adjNode = graph[v]
RuntimeError: maximum recursion depth exceeded in cmp
First of all, I'm not quite sure why the error is occurring in adjNode = graph[v] since explore is the recursive call and adjNode is just list assignment.
But to deal with the recursion error, I increased the recursion limit with sys.setrecursionlimit(5000) I no longer get the error, but the program quits right before the adjNode = graph[v] line and exits with no error. It never even reaches the end of dfs so I'm not quite sure what's going on. Thanks for reading all this and for any help!
Python is not very good at recursion. It doesn't do any tail-call optimization, and runs out of frame space pretty quickly unless you manually change the recursion limit. It's also slower to lookup and call a function again instead of keeping code in a loop without recursion.
Try rewriting this without recursion instead. The error can be happening anywhere a new frame is created, not just where your recursive call is, which is why the error is happening there.
def explore(graph, v):
visited.append(v)
adjNode = graph[v]
for i in range(0, len(adjNode)):
if not adjNode[i] in visited:
explore(graph, adjNode[i])
This isn't making sense to me, what is in a node object? Why are you assigning adjNode back to the value of the node that you pass in. Is adjNode meant to be calling like a "GetConnections()" sort of function instead?
The logic currently feels like it should be this:
1. For each Node in Nodes:
2. Add Node to visited
Get Nodes Connections
Explore SubNodes:
Go to 2.