Graph and Dijkstra in python - python

As another homework I have to do a Dijsktra's algorithm, but I'm not sure how to create a graph and if my implementation is right.
I have to use a given pattern that look like this:
class Vertex:
def __init__(self, id, name):
self.id = id
self.name = name
self.minDistance = None
self.previousVertex = None
self.edges = []
class Edge:
def __init__(self, source, target, weight):
self.source = source
self.target = target
self.weight = weight
class Dijkstra:
def __init__(self):
self.vertexes = Vertex
def createGraph(self, vertexes, edgesToVertexes):
pass
def getVertexes(self):
pass
def computePath(self, sourceId):
pass
def getShortestPathTo(self, targetId):
pass
def resetDijkstra(self):
pass
While calling a createGraph function it gives me two arrays: vertexes & edgesToVertexes containing Vertexes and Edges.
So how do I exactly extract data from these arrays and Initialize them as objects into both classes?

Related

Observer pattern updating after unsubscribing

I am currently trying to implement the observer design pattern on a List class. The list class is the subject, and a calculate class is the observer. The calculate class needs to observe the list class, and calculate the sum of the values in the list in the list class. However, when the observer unsubscribes from the List, it is still getting the updates. And if the observer subscribes to a new list, the list before unsubscribing is still showing. Does anyone have any tips to why this happens?
from abc import ABCMeta, abstractmethod
class Observer(metaclass = ABCMeta):
#abstractmethod
def update(self, data):
pass
class Subject(metaclass = ABCMeta):
#abstractmethod
def subscribe(self, observer):
pass
#abstractmethod
def unsubscribe(self, observer):
pass
#abstractmethod
def notify(self):
pass
class List(Subject):
def __init__(self):
self.__list = []
self._observers = set()
def add(self, data):
self.__list.append(data)
self.notify()
def subscribe(self, observer):
self._observers.add(observer)
def unsubscribe(self, observer):
self._observers.discard(observer)
def notify(self):
for obs in self._observers:
obs.update(self.__list)
class Calculate(Observer):
def __init__(self, lst):
self.__data = []
self._list = lst
self._list.subscribe(self)
def update(self, data):
self.__data = data
def calculate(self):
total = 0
for item in self.__data:
total += item
return total
def remove(self):
self._list.unsubscribe(self)
def attach(self, lst):
self._list.subscribe(self)
So, this is my test and the output i get:
first_list = List()
first_list.add(1)
list_observer = Calculate(first_list)
first_list.add(5)
list_observer.calculate()
This returns 6, which is correct. However, when i do this:
list_observer.remove()
first_list.add(5)
list_observer.calculate()
I get 11. Which in sense, is the correct calculation, but since the observer unsubscribed, why is it still getting the updates? I also tried subscribing to a new list, but the old data is still in there.
This has to do with the type of data you pass. The list of data is mutable. I can't explain it that well, but this answer is what you are looking for.
How do I pass a variable by reference?
You can fix it by doing this, you take a copy of the original object:
def update(self, data):
self.__data = data.copy()

Derived class with differing interface

The following code:
class Cache:
def __init__(self):
self._cache = []
def store(self, data):
self._cache.append(data)
def stats(self):
print('We are caching {} elements'.format(len(self._cache)))
class LegoCache(Cache):
def store(self, weight, color):
Cache.store(self, (weight, color))
has a problem in that the store method does not implement the interface of the base class.
How can this code be improved? I have the following ideas:
do not derive from Cache, just make use of it.
rename the store method in the base class to store_base
Are there other alternatives?
EDIT
The base class must also support this other use case:
class ZombieCache(Cache):
def store(self, dead_since, humans_eaten, can_be_saved=False):
Cache.store(self, dict(
dead_since=dead_since,
humans_eaten=humans_eaten,
can_be_saved=can_be_saved))
You may use a variable argument list in the base class:
class Cache:
def __init__(self):
self._cache = []
def store(self, *args):
self._cache.append(args)
def stats(self):
print('We are caching {} elements'.format(len(self._cache)))
class LegoCache(Cache):
pass
# "overloading" store isn't needed
So it isn't needed to overload this method or add methods with different names for specials cases:
cache = Cache()
legoCache = LegoCache()
cache.store(x)
legoCache.store(x, y)
Another solution may be delegation:
class LegoCache(object):
def __init__(self):
self.cache = Cache()
def store(self, weight, color):
self.cache.store((weight, color))
# or just self.cache.store(weight, color) if you use the *args implementation
I would implement it like this,
class Cache:
def __init__(self):
self._cache = []
def store(self, data):
self._cache.append(data)
def stats(self):
print('We are caching {} elements'.format(len(self._cache)))
class LegoData(object):
def __init__(self, weight, color):
self.weight = weight
self.color = color
class LegoCache(Cache):
pass
Client will access it like this,
lego_cache = LegoCache()
lego_cache.store(LegoData(weight=10, color='Green'))

Python - inner class is not defined?

I have to do an unrolled linked list for one of my classes. I'm new to python, but not to programming, and for some reason I cannot get around this little problem!
I have a class Node that is to be the node object used within the unrolled linked list. The unrolled linked list class performs all the operations on the Node class.
class UnrolledLinkedList(object):
""" INNER NODE CLASS """
class Node(object):
def __init__(self):
self.array = []
self.next_node = None
""" END NODE CLASS """
def __init__(self, max_node_capacity=16):
self.max_node_capacity = max_node_capacity
self.head = Node()
""" OTHER FUNCTIONS OF UNROLLEDLINKEDLIST CLASS """
The problem comes at the last line of the UnrolledLinkedList class' init function: "global name Node is not defined". I double checked my indentation and looked all over the internet for examples of something like this, but couldn't find any. Would someone mind explaining to me what's wrong?
Methods do not include their class as a scope to be searched. If you want this to work then you will need to use either UnrolledLinkedList.Node or self.Node instead.
The inner class Node is a member of the class UnrolledLinkedList and can only be accessed via self.
def __init__(self, max_node_capacity=16):
self.max_node_capacity = max_node_capacity
self.head = self.Node()
Use:
self.head = self.Node()
and it works.
A class does not create its own name space. Using self.Node(), Python first searches all attributes of the instances. Since it does not find the name Node there, it it searches the class UnrolledLinkedList for Node.
Alternatively, you can use the class name directly:
UnrolledLinkedList.Node()
You can achieve the same without nesting the class Node:
class Node(object):
def __init__(self):
self.array = []
self.next_node = None
class UnrolledLinkedList(object):
def __init__(self, max_node_capacity=16):
self.max_node_capacity = max_node_capacity
self.head = Node()
Qualify Node() with self:
class UnrolledLinkedList(object):
class Node(object):
def __init__(self):
self.array = []
self.next_node = None
def __init__(self, max_node_capacity=16):
self.max_node_capacity = max_node_capacity
self.head = self.Node()
Python needs to qualify references to things. In this case, you could either say UnrolledLinkedList.Node() or self.Node().

Implement and/or tree in python

I need to implement an And/or tree in python so I can evaluate boolean expressions,
I had an idea of creating a class that contains andNode, orNode and leafNode. The first two are are internal nodes that must have and or or values, the leafNode must have and integer value and represent the final leaves of the tree.I tried this but it doesn't seem to work:
class Node:
def __init__(self,leaf):
self.orNode = None
self.andNode = None
self.leaf = leaf
class and_or_tree (Node):
def __init__(self):
self.root=None
I need to test if an element exists in the tree, the height and iterate through it.
I think an example of such Leaf and and/or nodes could be something like this:
class Leaf:
def __init__(self, v):
self.val = v;
def __call__(self):
return self.val
class AndNode:
def __init__(self, l, r):
self.left = l;
self.right = r;
def __call__(self):
return self.left() and self.right()
class OrNode:
def __init__(self, l, r):
self.left = l;
self.right = r;
def __call__(self):
return self.left() or self.right()
You can build a tree like this:
print AndNode(Leaf(True), Leaf(False))()
print AndNode(OrNode(Leaf(True), Leaf(False)), Leaf(True))()
Which outputs this:
False
True

Class "super" variable

There is a class as following:
class N:
def __init__(self, node_id):
self.id = node_id # id (as an integer for example)
self.super = 0
self.color = 0
It is about creating a node. As you can see, there is an attribute, super. I want to call the color of the supernode.
I tried to implement:
node.color = node.super.color
but, it was wrong implementation. Do you have any idea how to get the information of other node?
You need to explicitly pass the parent node -or at least its color, to the class init function
- there is no way a simplist node class can "guess" how it is connected with other node objects.
One way to go is:
class N(object):
def __init__(self, node_id, parent_node):
self.id = node_ide
self.parent = parent_node
self.color = 0
# and you canget parentnode color with self.node.color

Categories

Resources