FAQ: Graphs: Python - Building the Graph II

This community-built FAQ covers the “Building the Graph II” exercise from the lesson “Graphs: Python”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Computer Science

Complex Data Structures

FAQs on the exercise Building the Graph II

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

Why do you have to key in to self.graph_dict here? All that you get out is something you already have in the form of to_vertex or from_vertex

4 Likes

self.graph_dict[from_vertex.value].add_edge(to_vertex.value)

This is a bit complex to understand, what does this do?also add_edge function is not imported in graph.py so how does it work there?

7 Likes

Same question here. Did you ever figure this out, or does someone else know?

1 Like

Hi,
I´m currently at 6 out of eleven and I have the same issue like you. Even if I understand it, it’s not really making a lot of sense right now, but hey it could be in the end of the lesson. I will let you know…

Like the most of you I used the shortcut:

	from_vertex.add_edge(to_vertex)
	# if the graph is not directed, do the following:
	if not self.directed:
		to_vertex.add_edge(from_vertex)

Anyway, here is my code for the vertex glass and graph class so far. I also made a print_dict() funktion in the graph class, to make it more visuel. I hope my comments in the code are helpful. Feedback is always welcome.

Vertex Class functions:

def get_edges(self):
	""" returns the keys of the dictionary"""
	#return list(self.edges.keys())
	print("\n***********************************")
	print("     Current Vertex Station        ")
	print("***********************************")

	edge_count = len(self.edges)
	print("The vertex '{vertex}' has {edge_count} connection(s).".format(vertex=self.value,edge_count=edge_count))
	if edge_count > 0:
		for key in self.edges:
			print("+ '{vertex}'".format(vertex=key.value))
	#return self.edges.keys()

def add_edge(self,vertex):
	print("\n***********************************")
	print("   + Adding Vertex Connection +   ")
	print("***********************************")
	"""vertex will be the value of another vertex"""
	print("Starting at '{vertex}'.".format(vertex = self.value))
	print("  '|'  ")
	print("Adding edge to '{vertex}'.".format(vertex = vertex.value))
	self.edges[vertex] = True

Graph Class Functions:

def add_vertex(self,vertex):
	print("\n***********************************")
	print("     + Adding Graph Station +     ")
	print("***********************************")
	print("\nThe vertex '{vertex}' which all his connections has been added to the graph.".format(vertex = vertex.value))

	"""dic[new key] = new value"""
	# dic = {'Grand Central Station' : Vertex} 
	# Vertex is {'Grand Central Station' : Vertex,Vertex....} Station : other conections
	# dict{'Grand Central Station' : dict{42nd Street Station':True]}}
	#vertex.value == content of varibale / vertex == variable
	self.graph_dict[vertex.value] = vertex

	print("\nThis is the content of the graph dictionary:")
	print(self.graph_dict)


def add_edge(self,from_vertex,to_vertex):
	# dict{key:Vetex Class Object} > dict{variable: value}
	# in Graph dict find Key > from_vertex = staion
	# take the value of the Key > .value = "Ballahoo"
	# call .add_edge(value) from Vertex class on the dict
	# returns
	# dict{"Ballahoo" : {Vertex variable : connections}} 
	
	#self.graph_dict[from_vertex.value].add_edge(to_vertex.value)
	from_vertex.add_edge(to_vertex)

	# if the graph is not directed, do the following:
	if not self.directed:
		#self.graph_dict[to_vertex.value].add_edge(from_vertex.value)
		to_vertex.add_edge(from_vertex)

	# call get_edges from Vertex Class to get content
	#self.graph_dict[from_vertex.value].get_edges()
	#self.graph_dict[to_vertex.value].get_edges()
	self.print_dict()

def print_dict(self):
	vertex_count = len(self.graph_dict)
	print("\n|||||||||||||||||||||||||||||||||||||||||")
	print("_____________GRAPH OVERVIEW______________")
	print("|||||||||||||||||||||||||||||||||||||||||")
	print("\nThis graph has {vertex_count} vertices.\n".format(vertex_count=vertex_count))
	for key in self.graph_dict:
		self.graph_dict[key].get_edges()

Funktions Calls:

railway = Graph()

#Make the Vertex instance here
station_a = Vertex(“Grand Central Station”)
station_b = Vertex(“Ballahoo”)

station_c = Vertex(“Station C”)
station_d = Vertex(“Station D”)
station_e = Vertex(“Station E”)

#Call .add_vertex() here
railway .add_vertex(station_a)
railway .add_vertex(station_b)
railway .add_vertex(station_c)
railway .add_vertex(station_d)
railway .add_vertex(station_e)

#Call .add_edge() from Vertex class here (from vertex to vertex)
station_a.add_edge(station_b)

#Call .add_edge() from Graph class here (graph.from vertex to vertex)
railway.add_edge(station_c,station_d)
railway.add_edge(station_d,station_e)

Output:

1 Like

update:

I finished the lesson and as far as I can say, it didn’t make much sense to me. I guess I solved it differently. I also noticed in the find_path method the cycle problem to quick, because I thought task 10 and 11 will be about the weight.Unfortunately not. Finding a path is cool, finding out the best path is better I guess. Maybe I will include the weight in the future. But for now I would like to share my methode, which looks a bit different, with you. Feedback is always welcome.

def find_path(self,start_vertex,end_vertex):
	print("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
	print("         + Finding Path +          ")
	print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")


	start = [start_vertex]
	already_visit_list = []
	print("\nTrying to find a path between '{start}' and '{end}'.".format(start=start_vertex.value,end=end_vertex.value))
	
	while len(start) > 0:
		# pop return and del the first item in the list
		current_vertex = start.pop(0)
		if current_vertex == end_vertex:
			print("Ending at '{vertex}'.".format(vertex = current_vertex.value))
			return True
		else: #chaining
			# add vertex to the already visit list
			already_visit_list.append(current_vertex)
			connections = current_vertex.get_edges()
			for connection in connections:
				if connection in already_visit_list:
					continue
				else:
					print("Connection found!")
					start = [connection]
					break
				start = []
				break


	print("\nThere is no path to the end vertex in the currend graph.")
	return False

1 Like

i too am questioning this, If mutating a vertex outside of the graph does not mutate it in the graph it would make sense to do it this way.
i believe mutating a vertex outside of the graph would also mutate it in the graph.

i guess the way to frame the question is “when inserting an object to another object does it create a new instance of the same object and store it within the other object”
ie:
case 1:
object 1 inserted into object 2 = object1 in 2 different locations

or

case 2:
object1 inserted into object2 = object3

if case 1 is true then calling self.graph_dict[from_vertex].add_edge(to_vertex) is unnecessary and can be replaced with from_vertex.add_edge(to_vertex)

EDIT:
the code in picmansmodels post is proof that case 1 is correct.
as for the pythonic way of doing this, based on PEP8 guidelines i would say from_vertex.add_edge(to_vertex) is a better way of doing this.
maybe on the further lesson on time complexity we will discover that this increases runtime.

3 Likes

I’m wondering the exact same thing

me too i found it complex

From my understanding of self.graph_dict[from_vertex.value].add_edge(to_vertex.value), You need to look at the script and realize that there are two vertex objects (station 1 and station 2), and we added them into the railway (graph’s instance object) by using graph’s method: .add_vertex().
This added both station_1, and station_2, into the railway’s graph_dict (dictionary) in a format of {{station’s name (key): stations’s instance object (value)}}. The name of the station is saved as the key and the vertex object is saved as the value.
Now back to self.graph_dict[from_vertex.value].add_edge(to_vertex.value),
The first part of the code “self.graph_dict[from_vertex.value]”, we are accessing the railway’s graph_dict and returning the station’s instance object (value) of the given Station’s name (key). To get the station’s name we would need to use .value this is because the object is a vertex object and we use .value to get the name of the station. once we got the right station name (key), it will return a vertex object (value) relative to the key.
The second part of the code:" add_edge(to_vertex.value)"
Now we have the vertex object we can call add_edge (this is possible because this method belongs to the vertex class) which will add [to_vertex.value (stations 2 string name): True] to the vertex object dictionary (self.edges: {}).

3 Likes

Ok, so I was thinking about this for a while and it ocurred to me that even though we don’t import add_edge from Vertex class into Graph class, we do this thing in script.py!!
1
What I mean is that we write Vertex and Graph separately from each other but they actually start working together after we import them and run it in script.py.

Now, about how self.graph_dict[from_vertex.value].add_edge(to_vertex.value, weight) works (as I understand it):
*peek at this block of code at script.py to help:

railway = Graph()
railway.add_vertex(callan)
railway.add_edge1(callan, peel, 12) #callan = from_vertex.value, peel=to_vertex=value, 12=weight

Now, step by step:

  1. self.graph_dict[from_vertex.value] --> in scrypt.py its “callan”, so we basically look for ‘callan’ in graph_dict.
  2. .add_edge(to_vertex.value, weight) --> we refer to Vertex class and we use add_edge method, which also have 2 properties (vertex and weight=0), from there. Basically, we call add_edge method from Vertex.

The if statement below in Graph goes through the same routine. Once again, Graph and Vertex classes can do nothing on their own but they start working together after we import both of them in script.py.

Hopefully, you and the future learners understand now how this thing works! It’s indeed written in a very confusing way and is hard to understand, so I hope I could help someone.

1 Like

Really thanks you !!!

1 Like

Why are we passing to_vertex.value? I thought add_edge was supposed to add the vertex object as key in the edge dictionary, with the vertex’s value as the value

1 Like

Thanks man, it really helped me.