Object is not callable? - python

Hi everyone I cannot figure out how to fix this issue and from my knowledge it's because of the attributes of the object's I am using.
For your information, I am making a graph in Python and the graph needs to check if all the vertices and edges are connected.
class graph(object):
def __init__(self, gdict=None):
if gdict == None:
gdict = {}
self.gdict = gdict
# return the keys of the dictionary list, or vertices
def getVertice(self):
return list(self.gdict.keys())
# this allows us to obtain the edges for the graph
# or "values" of the dict key
def getEdges(self):
return self.generate_edges()
def addVertex(self, vertex):
if vertex not in self.gdict:
self.gdict[vertex] = []
def addEdge(self, edge):
edge = set(edge)
(vertex1, vertex2) = tuple(edge)
if vertex1 in self.gdict:
self.gdict[vertex1].append(vertex2)
else:
self.gdict[vertex1] = [vertex2]
# this generates a list of all edges for the vertices
def generate_edges(self):
edges = []
for vertex in self.gdict:
for neighbour in self.gdict[vertex]:
if (neighbour, vertex) not in edges:
edges.append((vertex, neighbour))
return edges
def find_path(self, startVertex, endVertex, paths=None):
if paths == None:
paths = []
graphs = self.gdict
paths = paths + [startVertex]
if startVertex == endVertex:
return paths
if startVertex not in graphs:
return None
for vertex in graphs[startVertex]:
if vertex not in paths:
extendedPath = self.find_path(vertex, endVertex, paths)
if extendedPath:
return extendedPath
return None
def findAllPath(self, startVertex, endVertex, paths=None):
if paths is None:
paths = []
graphs = self.gdict
paths = paths + [startVertex]
if startVertex == endVertex:
return [paths]
if startVertex not in graphs:
return []
paths = []
for vertex in graphs[startVertex]:
if vertex not in paths:
extendedPath = self.find_path(vertex, endVertex, paths)
for p in extendedPath:
paths.append(p)
return paths
def findisovertices(self): ##reword this
""" returns a list of isolated vertices. """
graphs = self.gdict
iso = []
for vertex in graphs:
print(iso, vertex)
if not graphs[vertex]:
iso += [vertex]
return iso
def isConnected(self, verticesMet=None, startVertex=None):
if verticesMet is None:
verticesMet = set()
gdict = self.gdict
vertices = self.gdict()
if not startVertex:
startVertex = vertices[0]
verticesMet.add(startVertex)
if len(verticesMet) != len(vertices):
for vertex in gdict[startVertex]:
if vertex not in verticesMet:
if self.isConnected(verticesMet, vertex):
return True
else:
return True
return False
# this function prints the nodes/vertices in the graph
def completeGraph(self):
Vertex = len(self.gdict.keys())
Edges = len(self.gdict.values())
answer = 2.0 * Edges / (Vertex * (Vertex - 1))
return answer
graph_elements = ({"a": ["d", "f"],
"b": ["c"],
"c": ["b", "c", "d", "e"],
"d": ["a", "c"],
"e": ["c"],
"f": ["a"],
"z": []
})
g = graph(graph_elements)
print("Our vertices are: \n", g.getVertice())
print("#1 | Generate list of all edges: \n", graph.generate_edges(g))
##2 Function to calculate isolated nodes of graph.
isolated = graph.findisovertices(g)
print("#2 | Find isolated nodes:\n", isolated)
# 3. Function to find a path from a start vertex to an end vertex
path = graph.find_path(g, "a", "c")
print("#3 | Find a path function: \n", path)
# 4. Function to find all the paths between a start vertex to an end vertex
allPaths = graph.findAllPath(g, "a", "e")
print("#4 | All paths function:\n", allPaths)
# 5. Function to check if graph is connected
connect = graph(g)
print("#5 | Connected graph function \n", connect.isConnected(g))
and I keep receiving the following error:
Traceback (most recent call last):
File "graphsAssign6.py", line 160, in <module>
print("#5 | Connected graph function \n", connect.isConnected(g))
File "graphsAssign6.py", line 95, in isConnected
vertices = self.gdict()
TypeError: 'graph' object is not callable

def isConnected(self, verticesMet=None, startVertex=None):
if verticesMet is None:
verticesMet = set()
gdict = self.gdict
vertices = self.getVertice()
if not startVertex:
startVertex = vertices[0]
verticesMet.add(startVertex)
if len(verticesMet) != len(vertices):
for vertex in gdict[startVertex]:
if vertex not in verticesMet:
if self.isConnected(verticesMet, vertex):
return True
else:
return True
return False
# 5. Function to check if graph is connected
print("#5 | Connected graph function \n", g.isConnected())
Don't make a new connect = graph(g). Your isConnected should work within g. Also, you shouldn't get your vertices with self.gdict(). It doesn't make sense and you already have a function named getVertice for that job.

Related

Error while running a function more than a single time

The function only executes single time if I call it again it throws the keyError exception.
Function Call
Dijkstra.shortest_path(network_graph, 'Delhi', 'Kochin')
Dijkstra.shortest_path(network_graph, 'Chandigarh', 'Kolkata')
Function
def shortest_path(graph, src, dest) :
#print(src,dest)
shortest_distance = {}
visited = {}
unvisited = graph
path = []
for vertex in unvisited :
shortest_distance[vertex] = float('inf')
shortest_distance[src] = 0
while unvisited:
mincostV = None
for vertex in unvisited:
if mincostV is None:
mincostV = vertex
elif shortest_distance[vertex] < shortest_distance[mincostV]:
mincostV = vertex
for neighbour, weight in unvisited[mincostV].items():
if weight + shortest_distance[mincostV] < shortest_distance[neighbour]:
shortest_distance[neighbour] = weight + shortest_distance[mincostV]
visited[neighbour] = mincostV
unvisited.pop(mincostV)
currentVertex = dest
while currentVertex != src:
path.insert(0, currentVertex)
currentVertex = visited[currentVertex]
path.insert(0, src)
if shortest_distance[dest] != float('inf'):
#print('Shortest Distance is',shortest_distance[dest],'kms.')
print('via', path)
return path
The function shortest_path returns the shortest path between to vertices of a graph using Dijkstra's SPSP algorithm. I want to find the shortest path between multiple vertices, it is working only single time and throwing keyError exception when called with different parameters.

my implementation of dijkstra algorithm in python using recursion

i'm beginner and this my implementation can you give you opinion about this algorithm .
I managed to build this algorithm after 3 days
I found lots of implementation but i found them confusing .
and I wanted to build it by myself.
class Graph:
def __init__(self, size):
self.edges = {}
self.cost = {}
def addNode(self, node):
self.edges[node] = {}
def addEdge(self, node1, node2,w):
self.edges[node1][node2] = w
def getSub(self, node):
return self.edges[node]
def getCost(self,node):
return self.cost[node]
def setCost(self, node1, node2, edge):
if self.getCost(node1) + edge < self.getCost(node2):
self.cost[node2] = self.getCost(node1) + edge
def getDistance(self,node1, node2,c):
return self.getSub(node1)[node2]+c
# this function travel all graph and update cost of each node
def Dijkstra(self, start, visited):
visited +=[start]
for child in self.getSub(start):
self.setCost(start, child, self.getSub(start)[child])
for node in self.getSub(start):
if node not in visited:
self.Dijkstra(node,visited)
# after we set cost for each node/ver we need this fun to find small dis
def Dijkstra_helper(self, start, end, paths, dis = 0):
paths += [start]
if start == end:
return paths
for node in self.getSub(start):
if end in paths:
break
if node not in paths:
new_dis = self.getDistance(start, node, dis)
"""
S -- 1-- c
\2 this just part of graph example if we come from A. the distance from A to B is 6 > 3 that's mean we should
A--6-->B(3) come from C if statement prevent as from continue in this path
"""
if new_dis <= self.getCost(node) and new_dis <=self.getCost(end):
self.Dijkstra_helper(node, end, paths, new_dis)
return paths
if __name__ == "__main__":
nodes = ["S","B","C","D",'E']
g = Graph(len(nodes))
for node in nodes:
g.addNode(node)
g.cost["S"] = 0
infinity = float('inf')
for n in nodes[1:]:
g.cost[n] = infinity
g.addEdge("S", "D",1)
g.addEdge('S', "B",6)
g.addEdge("B", "C",5)
g.addEdge("D", "E",1)
g.addEdge("D", "B",2)
g.addEdge("E", "B",2)
g.addEdge("E", "C",5)
g.Dijkstra("S",[])
print(g.cost)
print(g.Dijkstra_helper("S","C",[]))
I tested this algorithm in it works .but there's only one problem the shortest path depend on how you build your graph like if you put S--> D if the first it not like hen you put S --> B you can test the algorithm To understand what I want to say. Is there any way I could further optimize it?

AttributeError: 'list' object has no attribute 'dijkstra'+python

I'm trying to run this code but I get AttributeError:
File "D:/QGIS TRAINING/Masir/dkj.py", line 98, in
print(graph.dijkstra("905577", "703920")) AttributeError: 'list' object has no attribute 'dijkstra'
I make list from a csv file and set it as an input to my algorithm
here is my code
import csv
from collections import deque, namedtuple
with open('D:/QGIS TRAINING/Masir/yal zero.csv', 'r') as f:
reader = csv.reader(f)
list_nodes = list(reader)
# we'll use infinity as a default distance to nodes.
inf = float('inf')
Edge = namedtuple('Edge', 'start, end, cost')
def make_edge(start, end, cost=1):
return Edge(start, end, cost)
class Graph:
def __init__(self, edges):
# let's check that the data is right
wrong_edges = [i for i in edges if len(i) not in [2, 3]]
if wrong_edges:
raise ValueError('Wrong edges data: {}'.format(wrong_edges))
self.edges = [make_edge(*edge) for edge in edges]
#property
def vertices(self):
return set(
sum(
([edge.start, edge.end] for edge in self.edges), []
)
)
def get_node_pairs(self, n1, n2, both_ends=True):
if both_ends:
node_pairs = [[n1, n2], [n2, n1]]
else:
node_pairs = [[n1, n2]]
return node_pairs
def remove_edge(self, n1, n2, both_ends=True):
node_pairs = self.get_node_pairs(n1, n2, both_ends)
edges = self.edges[:]
for edge in edges:
if [edge.start, edge.end] in node_pairs:
self.edges.remove(edge)
def add_edge(self, n1, n2, cost=1, both_ends=True):
node_pairs = self.get_node_pairs(n1, n2, both_ends)
for edge in self.edges:
if [edge.start, edge.end] in node_pairs:
return ValueError('Edge {} {} already exists'.format(n1, n2))
self.edges.append(Edge(start=n1, end=n2, cost=cost))
if both_ends:
self.edges.append(Edge(start=n2, end=n1, cost=cost))
#property
def neighbours(self):
neighbours = {vertex: set() for vertex in self.vertices}
for edge in self.edges:
neighbours[edge.start].add((edge.end, edge.cost))
return neighbours
def dijkstra(self, source, dest):
assert source in self.vertices, 'Such source node doesn\'t exist'
distances = {vertex: inf for vertex in self.vertices}
previous_vertices = {
vertex: None for vertex in self.vertices
}
distances[source] = 0
vertices = self.vertices.copy()
while vertices:
current_vertex = min(
vertices, key=lambda vertex: distances[vertex])
vertices.remove(current_vertex)
if distances[current_vertex] == inf:
break
for neighbour, cost in self.neighbours[current_vertex]:
alternative_route = distances[current_vertex] + cost
if alternative_route < distances[neighbour]:
distances[neighbour] = alternative_route
previous_vertices[neighbour] = current_vertex
path, current_vertex = deque(), dest
while previous_vertices[current_vertex] is not None:
path.appendleft(current_vertex)
current_vertex = previous_vertices[current_vertex]
if path:
path.appendleft(current_vertex)
return path
graph = list_nodes
print(graph.dijkstra("905577", "703920"))
is it something wrong with my list or with the algorithm?
There's the problem with the way you instantiate the graph object. You see, this:
graph = list_nodes
is a list of nodes from list_nodes = list(reader).
But this:
graph = Graph(list_nodes)
is probably what you actually want.
Just in case, here's a DigitalOcean tutorial on object construction

'str' object has no attribute / error calling a dictionary

I have a class with a function that adds an edge to the graph, according to the input given. For example: if the input is add James Larry 1, an edge will be added between James and Larry with the weight (intimacy level) 1. The graph is a dictionary of sets, so, the keys are the node and the values (sets) are the edges.
So, this function has as parameters: the source, the destination and the weight. The class is represented below:
class DiGraph(object):
# Create an empty graph.
def __init__(self):
## A dictionary that stores an entry of a node, as the key, and a set of outgoing edges
# (destination node, weight) from the node, as its value.
self.graph = {}
## Total number of edges in the graph.
self.__numEdges = 0
## The largest edge distance.
# self.__infinity = sys.maxint
self.__infinity = sys.maxsize
## Holds the path from a source node to a given node.
self.__pathToNode = None
## Accumulated distance from source to a node.
self.__dist = None
### (...)
def addEdge(self, src, dst, c=1):
if ( src == None or dst == None or c <= 0 or src == dst ):
return False
# the edge set of src
eSet = self.graph.get(src)
e = Edge(dst,c) # new edge
if eSet == None:
# no edge starting at src, so create a new edge set
eSet = set()
self.__numEdges += 1
else:
ed = self.getEdge(src,dst)
if ( ed != None ):
ed.setCost(c)
return True
else:
self.__numEdges += 1
eSet.add(e) # a set does not have duplicates
self.graph[src] = eSet
if not self.hasVertex(dst):
self.addVertex(dst)
return True
I am trying to implement this code:
import DiGraph
#Create an empty graph
def main():
aGraph = {}
f = open("infile.txt")
contents = f.read()
lines = contents.splitlines()
word = []
for line in lines:
word.append(line.split())
for i in range(len(word)):
if word[i][0] == 'add':
aGraph = DiGraph.DiGraph.addEdge(word[i][1], word[i][2], int(word[i][3]))
return aGraph
grafo = main()
And the first line of the file is: add James Larry 1
This error is being showed to me when I try to run this code:
Traceback (most recent call last):
File "C:/.../SocialGraph.py", line 24, in
grafo = main()
File "C:/.../SocialGraph.py", line 20, in main
aGraph = DiGraph.DiGraph.addEdge(word[i][1], word[i][2], int(word[i][3]))
File "C:...\DiGraph.py", line 156, in addEdge
eSet = self.graph.get(src)
AttributeError: 'str' object has no attribute 'graph'
What can I do to correct this?
DiGraph.DiGraph.addEdge(word[i][1],
You call this as a static method. 'word[i][1]' becomes 'self'.
You implement addEdge as an instance method so that you have to create an instance to use it. Like so:
# create DiGraph instance
diGraph = DiGraph.DiGraph()
for i in range(len(word)):
if word[i][0] == 'add':
aGraph = diGraph.addEdge(word[i][1], word[i][2], int(word[i][3]))

Python - Dijsktra's Algorithm Distance Problem

I've run into a problem with my code, i'm not able to calculate the distance to a node from the starting node. I have a text file of the form:
1,2,3,4,5,6,7,8,9
1,2,3,4,5,6,7,8,9
This represents the node distances in the graph. Here is my code, unfortunately, despite trying a few different methods I still keep coming up with various error messages.
infinity = 1000000
invalid_node = -1
startNode = 0
class Node:
distFromSource = infinity
previous = invalid_node
visited = False
def populateNodeTable():
nodeTable = []
index =0
f = open('route.txt', 'r')
for line in f:
node = map(int, line.split(','))
nodeTable.append(Node())
print nodeTable[index].previous
print nodeTable[index].distFromSource
index +=1
nodeTable[startNode].distFromSource = 0
return nodeTable
def tentativeDistance(currentNode, nodeTable):
nearestNeighbour = []
for currentNode in nodeTable:
# if Node[currentNode].distFromSource + currentDistance = startNode + currentNode
# currentDistance = currentNode.distFromSource + nodeTable.currentNode
currentNode.previous = currentNode
currentNode.length = currentDistance
currentNode.visited = True
currentNode +=1
nearestNeighbour.append(currentNode)
print nearestNeighbour
return nearestNeighbour
def shortestPath (nearestNeighbour)
shortestPath = []
f = open ('spf.txt', 'r')
f.close()
currentNode = startNode
if __name__ == "__main__":
populateNodeTable()
tentativeDistance(currentNode,populateNodeTable())
The lines starting with '#' in my tentativeDistance function is the section giving me trouble. I've looked at some other implementations on the web though they confuse me
I have been programming the Dijkstra's Algorithm in Python a few months ago; its tested and it should work:
def dijkstra(u,graph):
n = graph.numNodes
l = { u : 0 } ; W = graph.V()
F = [] ; k = {}
for i in range(0,n):
lv,v = min([ (l[lk],lk) for lk in l.keys() if lk in W ])
W.remove(v)
if v!=u: F.append(k[v])
for v1 in [ v2 for v2 in graph.G(v) if v2 in W ]:
if v1 not in l or l[v]+graph.w(v,v1) < l[v1]:
l[v1] = l[v] + graph.w(v,v1)
k[v1] = (v,v1)
return l,F
You need a class Graph with Method V() (which yields the graphs nodes), w(v1,v2) (which yields the weight of the edge (v1,v2)), remove (which removes an edge from a graph) and attribute numNodes (which yields the number of nodes in the graph) and G(v) which yields the neighborhood of node v.

Categories