0

See full working directory here: https://github.com/sharpvik/python-libs/tree/alpha/Testing

So I was working on some Graph theory and coding stuff in Python. I created a class called Graph as follows (don't worry about indentation, in the file itself it's fine):

class Graph:                                            # undirected graph; no values for the edges;
def __init__(self):
    self.nodes_counter = 0
    self.nodes_dict = dict()

def node_add(self, name):                           # name(int / str) -- name of the node;
    self.nodes_dict.update( { name : list() } )
    self.nodes_counter += 1
    return name

def node_del(self, name):                           # name(int / str) -- name of the node;
    self.nodes_dict.pop(name, None)
    for each in self.nodes_dict:
        self.nodes_dict[each].remove(name)
    self.nodes_counter -= 1
    return name

def connection_add(self, one, two):                 # one(int / str) and two(int / str) -- two nodes you want to connect;
    self.nodes_dict[one].append(two)
    self.nodes_dict[two].append(one)
    return [one, two]

def connection_del(self, one, two):                 # one(int / str) and two(int / str) -- two nodes you want to disconnect;
    self.nodes_dict[one].remove(two)
    self.nodes_dict[two].remove(one)
    return [one, two]

def nodes_count(self):                              # --> function returns the number of nodes in the graph;
    return self.nodes_counter

def nodes_return(self):                             # --> function returns the whole dict containing nodes and their connections;
    return self.nodes_dict

def node_return(self, name):                        # name(int / str) -- name of the node you're checking;
                                                    # --> function returns connections of the given node;
    return self.nodes_dict[name]

# search

## --> breadth first search using class Queue
def bfs( self, final, queue=Queue(None), checked=list() ):      # final(int / str) -- name of the node you're trying to establish connection with;
                                                                # queue(class Queue) -- Queue containing the element you are beginning with (format: element);
                                                                # checked(list) -- leave empty *** internal use ***;
                                                                # --> function returns True if the two nodes are connected, otherwise it returns False;
    if queue.length() == 0:
        return False
    temp = queue.pop()
    if temp == final:
        return True
    else: 
        checked.append(temp)
        for child in self.node_return(temp):
            if child not in checked:
                queue.ins(child)
        return self.bfs(final, queue, checked)
## breadth first search using class Queue <--

## --> depth first serach using class Stack
def dfs( self, final, stack=Stack(None), checked=list() ):      # final(int / str) -- name of the node you're trying to establish connection with;
                                                                # stack(class Stack) -- Stack containing the element you are beginning with (format: element);
                                                                # checked(list) -- leave empty *** internal use ***;
                                                                # --> function returns True if the two nodes are connected, otherwise it returns False;
    if stack.length() == 0:
        return False
    temp = stack.pop()
    if temp == final:
        return True
    else:
        checked.append(temp)
        for child in self.node_return(temp):
            if child not in checked:
                stack.add(child)
        return self.dfs(final, stack, checked)
## depth first serach using class Stack <--

The bfs and dfs functions in the end rely on my other two classes:

class Stack:
def __init__(self, element):
    if isinstance(element, list):
        self.storage = element
    else:
        self.storage = [element]

def add(self, element):
    self.storage.append(element)
    return element

def pop(self):
    temp = self.storage[-1]
    self.storage.pop(-1)
    return temp

def length(self):
    return len(self.storage)

and

class Queue:
def __init__(self, element):
    if isinstance(element, list):
        self.storage = element
    else:
        self.storage = [element]

def ins(self, element):
    self.storage.insert(0, element)
    return element

def pop(self):
    temp = self.storage[0]
    self.storage.pop(0)
    return temp

def length(self):
    return len(self.storage)

Now, in another file I've initialized a new Graph that I called g for simplicitiy and tested on it.

print("BFS for 1 and 2 # --> should return True")
print( g.bfs(2, Queue(1) ), end="\n\n" )

print("BFS for 1 and 4 # --> should return True")    # but returns False!!!
print( g.bfs(4, Queue(1) ), end="\n\n" )

Now, when I started debugging it, I've noticed that the checked list that keeps track of checked nodes for some reason stays full of the nodes checked by the first call to the function, even though I have implicitly set it to be checked=list() in the def bfs(...) declaration so that it will be empty every time someone calls the function. This unusual behaviour causes it to not check the node 4 because it thinks that it had already been checked (checked = [1, 3, 4]), therefore the second time function decides that two nodes aren't connected and returns False.

This problem can be solved if I pass [] empty list after the Queue(1) like that:

print( g.bfs(4, Queue(1), [] ) )

However this would complicate things and I also just want to know why it does that anyways. So if anyone knows what the hell is happening here, I am looking forward to your response.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • 1
    (Meta advice: it's best not to edit voting commentary into questions. Add a comment instead, explaining _why_ you believe it is not a duplicate, and remember that an experienced poster made that decision in good faith. Avoid all caps when representing your view please.) – halfer May 12 '18 at 18:32
  • @halfer ok, sorry, I was stressed out. You're right. – Viktor Rozenko May 12 '18 at 18:34
  • No worries - even long-standing users here sometimes get a vote or close they don't like. It happens `:-)` – halfer May 12 '18 at 18:35

0 Answers0