Glab S15 Rusnayo 2023 01

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 22

ESTRUCTURA DE DATOS Y ALGORITMOS

LABORATORIO N° 15
GRAFOS

Alumno Nota
Urquizo Apaza, Josue Alessandro
Grupo D
Fecha de Entrega 03/07/2023
Docente Renato Usnayo Cáceres

DISEÑO Y DESARROLLO DE SOFTWARE


PROGRAMA DE FORMACIÓN REGULAR
Laboratorio de Estructura de Datos y Algoritmos Página | 1

OBJETIVOS:
• Conocer, comprender y aplicar el uso de Grafos como una forma de almacenar datos en la
resolución de problemas de software.

SEGURIDAD:

Advertencia:
En este laboratorio está prohibida la manipulación del hardware, conexiones
eléctricas o de red; así como la ingestión de alimentos o bebidas.

FUNDAMENTO TEÓRICO:
• Revisar el texto guía que está en el campus Virtual.

NORMAS EMPLEADAS:
• No aplica

RECURSOS:
• En este laboratorio cada alumno trabajará con un equipo con Windows 10.

METODOLOGÍA PARA EL DESARROLLO DE LA TAREA:


• El desarrollo del laboratorio es individual.

PROCEDIMIENTO:
Nota:

Las secciones en cursivas son demostrativas, pero sirven para que usted pueda instalar las
herramientas de desarrollo en un equipo externo.

EJERCICIO DE APLICACIÓN

Introducción a los Grafos

Los grafos son estructuras de datos que representan relaciones entre elementos. Están compuestos por
nodos (vértices) y arcos (aristas) que conectan los nodos. Python ofrece varias bibliotecas populares
para trabajar con grafos, como NetworkX y igraph. En esta guía, nos centraremos en la biblioteca
NetworkX.

Paso 1: Instalación

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 2

Antes de empezar, asegúrate de tener instalada la biblioteca NetworkX en tu entorno de Python. Puedes
instalarlo usando pip:

pip install networkx

Paso 2: Creación de un Grafo

Comencemos creando un grafo vacío. Importa la biblioteca NetworkX y crea un objeto de grafo:

import networkx as nx
G = nx.Graph()

Hemos creado un grafo no dirigido llamado G. Ahora, podemos agregar nodos y aristas a este grafo.

Paso 3: Agregar Nodos y Aristas

Para agregar nodos al grafo, utilizamos el método add_node() y pasamos el identificador del nodo como
argumento:

G.add_node(1)
G.add_node(2)
G.add_node(3)

También podemos agregar varios nodos a la vez usando el método add_nodes_from() y pasando una
lista de identificadores:

nodes = [4, 5, 6]
G.add_nodes_from(nodes)

Para agregar aristas, utilizamos el método add_edge() y pasamos los identificadores de los nodos que
queremos conectar:

G.add_edge(1, 2)
G.add_edge(2, 3)
G.add_edge(3, 1)

Del mismo modo, podemos agregar varias aristas a la vez usando el método add_edges_from() y
pasando una lista de pares de nodos:

edges = [(4, 5), (5, 6), (6, 4)]

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 3

G.add_edges_from(edges)

Paso 4: Visualización del Grafo

Para visualizar el grafo, podemos utilizar la función draw() de NetworkX junto con la biblioteca
Matplotlib. Asegúrate de tener instalada la biblioteca Matplotlib.

import matplotlib.pyplot as plt

nx.draw(G, with_labels=True)
plt.show()

import networkx as nx
import matplotlib.pyplot as plt

# Crear un grafo vacío


G = nx.Graph()

# Agregar nodos individuales


G.add_node(1)
G.add_node(2)
G.add_node(3)

# Agregar varios nodos a la vez


nodes = [4, 5, 6]
G.add_nodes_from(nodes)

# Agregar aristas individuales


G.add_edge(1, 2)
G.add_edge(2, 3)
G.add_edge(3, 1)

# Agregar varias aristas a la vez


edges = [(4, 5), (5, 6), (6, 4)]
G.add_edges_from(edges)

# Visualizar el grafo
nx.draw(G, with_labels=True)
plt.show()

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 4

Esto mostrará una representación gráfica del grafo con etiquetas en los nodos. Puedes ajustar los estilos
y la disposición del grafo según tus necesidades.

Ejercicio 1: Creación y Visualización de un Grafo

Crea un grafo llamado my_graph con 5 nodos y 6 aristas. Los identificadores de los nodos deben ser
números enteros del 1 al 5. Añade las aristas para que el grafo forme un ciclo cerrado. Luego, visualiza el
grafo utilizando la función draw().

import networkx as nx
import matplotlib.pyplot as plt

my_graph = nx.Graph()
nodes = [1, 2, 3, 4, 5]
edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 1), (1, 3)]
my_graph.add_nodes_from(nodes)

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 5

my_graph.add_edges_from(edges)

nx.draw(my_graph, with_labels=True)
plt.show()

Este código crea un grafo con 5 nodos y 6 aristas, formando un ciclo cerrado. Luego, se utiliza la función
draw() de NetworkX junto con la biblioteca Matplotlib para visualizar el grafo.

Captura de ejecución

import networkx as nx
import matplotlib.pyplot as plt

my_graph = nx.Graph()
nodes = [1, 2, 3, 4, 5]
edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 1), (1, 3)]
my_graph.add_nodes_from(nodes)
my_graph.add_edges_from(edges)

nx.draw(my_graph, with_labels=True)
plt.show()

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 6

Paso 5: Operaciones y Consultas en el Grafo

NetworkX proporciona una amplia gama de funciones para realizar operaciones y consultas en un grafo.
Aquí hay algunos ejemplos:

Para obtener la lista de nodos en el grafo:

nodes = G.nodes()
print(nodes)

Para obtener la lista de aristas en el grafo:

edges = G.edges()

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 7

print(edges)

Para verificar si un nodo está presente en el grafo:

if G.has_node(1):
print("El nodo 1 está presente en el grafo.")

Para verificar si una arista está presente en el grafo:

if G.has_edge(2, 3):
print("La arista entre los nodos 2 y 3 está presente en el grafo.")

Estas son solo algunas de las operaciones básicas disponibles en NetworkX. Puedes consultar la
documentación oficial para obtener más información sobre las operaciones y funciones avanzadas.

Ejercicio 2: Operaciones en un Grafo

Usando el grafo my_graph creado anteriormente, realiza las siguientes operaciones:

Imprime la lista de nodos en el grafo.

Imprime la lista de aristas en el grafo.

Verifica si el nodo 3 está presente en el grafo.

Verifica si la arista entre los nodos 4 y 5 está presente en el grafo.

nodes = my_graph.nodes()
print("Lista de nodos:", nodes)

edges = my_graph.edges()
print("Lista de aristas:", edges)

if my_graph.has_node(3):
print("El nodo 3 está presente en el grafo.")
else:
print("El nodo 3 no está presente en el grafo.")

if my_graph.has_edge(4, 5):
print("La arista entre los nodos 4 y 5 está presente en el grafo.")
else:
print("La arista entre los nodos 4 y 5 no está presente en el grafo.")

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 8

Esto imprimirá la lista de nodos y aristas en el grafo, y verificará la presencia del nodo 3 y la arista entre
los nodos 4 y 5 en el grafo.

import networkx as nx
import matplotlib.pyplot as plt

# Creación del grafo


my_graph = nx.Graph()
nodes = [1, 2, 3, 4, 5]
edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 1), (1, 3)]
my_graph.add_nodes_from(nodes)
my_graph.add_edges_from(edges)

# Visualización del grafo


nx.draw(my_graph, with_labels=True)
plt.show()

# Operaciones en el grafo
nodes = my_graph.nodes()
print("Lista de nodos:", nodes)

edges = my_graph.edges()
print("Lista de aristas:", edges)

if my_graph.has_node(3):
print("El nodo 3 está presente en el grafo.")
else:
print("El nodo 3 no está presente en el grafo.")

if my_graph.has_edge(4, 5):
print("La arista entre los nodos 4 y 5 está presente en el grafo.")
else:
print("La arista entre los nodos 4 y 5 no está presente en el grafo.")

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 9

Ejemplo de cómo declarar un grafo utilizando una matriz de adyacencia

class GrafoMatriz:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
self.matriz = [[0] * num_vertices for _ in range(num_vertices)]

def agregar_arista(self, origen, destino):


if origen >= self.num_vertices or destino >= self.num_vertices:
raise ValueError("Los vértices están fuera de rango")
self.matriz[origen][destino] = 1
self.matriz[destino][origen] = 1

def imprimir_grafo(self):
for fila in self.matriz:

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 10

print(fila)

# Ejemplo de uso
grafo = GrafoMatriz(5)

grafo.agregar_arista(0, 1)
grafo.agregar_arista(0, 4)
grafo.agregar_arista(1, 2)
grafo.agregar_arista(1, 3)
grafo.agregar_arista(1, 4)
grafo.agregar_arista(2, 3)
grafo.agregar_arista(3, 4)

grafo.imprimir_grafo()

En este ejemplo, la clase GrafoMatriz representa un grafo utilizando una matriz de adyacencia. La matriz
se inicializa con ceros y tiene un tamaño determinado por el número de vértices proporcionado al
constructor. Luego, puedes utilizar el método agregar_arista para indicar las conexiones entre los
vértices. Finalmente, el método imprimir_grafo muestra la matriz de adyacencia por pantalla.

En el ejemplo de uso, se crea un grafo con 5 vértices y se agregan varias aristas entre ellos. Luego se
imprime la matriz de adyacencia resultante.

Recuerda que en una matriz de adyacencia, el valor 1 indica la existencia de una arista entre dos
vértices, mientras que el valor 0 indica la ausencia de una arista.

Captura de ejecución

import networkx as nx
import matplotlib.pyplot as plt

class GrafoMatriz:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
self.matriz = [[0] * num_vertices for _ in range(num_vertices)]

def agregar_arista(self, origen, destino):


if origen >= self.num_vertices or destino >= self.num_vertices:
raise ValueError("Los vértices están fuera de rango")
self.matriz[origen][destino] = 1
self.matriz[destino][origen] = 1

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 11

def imprimir_grafo(self):
for fila in self.matriz:
print(fila)

grafo = GrafoMatriz(5)

grafo.agregar_arista(0, 1)
grafo.agregar_arista(0, 4)
grafo.agregar_arista(1, 2)
grafo.agregar_arista(1, 3)
grafo.agregar_arista(1, 4)
grafo.agregar_arista(2, 3)
grafo.agregar_arista(3, 4)

grafo.imprimir_grafo()

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 12

Imprimir el gráfico del grafo utilizando la biblioteca networkx y matplotlib

import networkx as nx
import matplotlib.pyplot as plt

class GrafoMatriz:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
self.matriz = [[0] * num_vertices for _ in range(num_vertices)]

def agregar_arista(self, origen, destino):


if origen >= self.num_vertices or destino >= self.num_vertices:
raise ValueError("Los vértices están fuera de rango")

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 13

self.matriz[origen][destino] = 1
self.matriz[destino][origen] = 1

def imprimir_grafo(self):
G = nx.Graph()
for i in range(self.num_vertices):
G.add_node(i)

for i in range(self.num_vertices):
for j in range(i + 1, self.num_vertices):
if self.matriz[i][j] == 1:
G.add_edge(i, j)

nx.draw(G, with_labels=True, node_color='lightblue', node_size=500, font_weight='bold')


plt.show()

# Ejemplo de uso
grafo = GrafoMatriz(5)

grafo.agregar_arista(0, 1)
grafo.agregar_arista(0, 4)
grafo.agregar_arista(1, 2)
grafo.agregar_arista(1, 3)
grafo.agregar_arista(1, 4)
grafo.agregar_arista(2, 3)
grafo.agregar_arista(3, 4)

grafo.imprimir_grafo()

Captura de ejecución

import networkx as nx
import matplotlib.pyplot as plt

class GrafoMatriz:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
self.matriz = [[0] * num_vertices for _ in range(num_vertices)]

def agregar_arista(self, origen, destino):


if origen >= self.num_vertices or destino >= self.num_vertices:
raise ValueError("Los vértices están fuera de rango")
self.matriz[origen][destino] = 1
self.matriz[destino][origen] = 1

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 14

def imprimir_grafo(self):
G = nx.Graph()
for i in range(self.num_vertices):
G.add_node(i)

for i in range(self.num_vertices):
for j in range(i + 1, self.num_vertices):
if self.matriz[i][j] == 1:
G.add_edge(i, j)

nx.draw(G, with_labels=True, node_color='lightblue', node_size=500,


font_weight='bold')
plt.show()

grafo = GrafoMatriz(5)

grafo.agregar_arista(0, 1)
grafo.agregar_arista(0, 4)
grafo.agregar_arista(1, 2)
grafo.agregar_arista(1, 3)
grafo.agregar_arista(1, 4)
grafo.agregar_arista(2, 3)
grafo.agregar_arista(3, 4)

grafo.imprimir_grafo()

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 15

Ejemplo de implementación de un grafo utilizando una matriz de adyacencia en Python:

class Graph:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
self.adj_matrix = [[0] * num_vertices for _ in range(num_vertices)]

def add_edge(self, source, destination):


if source >= 0 and destination >= 0 and source < self.num_vertices and destination <
self.num_vertices:
self.adj_matrix[source][destination] = 1
self.adj_matrix[destination][source] = 1

def remove_edge(self, source, destination):


if source >= 0 and destination >= 0 and source < self.num_vertices and destination <
self.num_vertices:

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 16

self.adj_matrix[source][destination] = 0
self.adj_matrix[destination][source] = 0

def print_graph(self):
for row in self.adj_matrix:
for val in row:
print(val, end=" ")
print()

# Crear un grafo con 5 vértices


graph = Graph(5)

# Agregar conexiones entre los vértices


graph.add_edge(0, 1)
graph.add_edge(0, 4)
graph.add_edge(1, 2)
graph.add_edge(1, 3)
graph.add_edge(1, 4)
graph.add_edge(2, 3)
graph.add_edge(3, 4)

# Imprimir el grafo
graph.print_graph()

En este ejemplo, la clase Graph representa un grafo y utiliza una matriz de adyacencia adj_matrix para
almacenar las conexiones entre los vértices. El tamaño de la matriz se establece en función del número
de vértices proporcionados al crear el grafo.

El método add_edge permite agregar una conexión entre dos vértices, estableciendo los valores
correspondientes en la matriz de adyacencia. El método remove_edge elimina una conexión existente,
estableciendo los valores correspondientes en la matriz a 0.

El método print_graph imprime la matriz de adyacencia en forma de grafo, donde los valores 1 indican
una conexión entre los vértices correspondientes.

En el ejemplo, se crea un grafo con 5 vértices y se agregan varias conexiones entre ellos. Luego, se
imprime la matriz de adyacencia resultante.

La salida del programa será:

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 17

01001
10111
01010
01101
11010

Esta matriz muestra las conexiones entre los vértices del grafo. Por ejemplo, el valor 1 en la posición (0,
1) indica que existe una conexión entre el vértice 0 y el vértice 1, y viceversa.

Generar el gráfico correspondiente al grafo en Python,

import networkx as nx
import matplotlib.pyplot as plt

# Crear el grafo utilizando networkx


G = nx.Graph()
G.add_edges_from([(0, 1), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (3, 4)])

# Dibujar el grafo
pos = nx.spring_layout(G) # Posiciones de los nodos utilizando el algoritmo de Spring layout
nx.draw(G, pos, with_labels=True, node_size=500, node_color='lightblue', font_size=12,
font_weight='bold', edge_color='gray')

# Mostrar el gráfico
plt.title("Grafo")
plt.show()

En este ejemplo, creamos un objeto de grafo G utilizando nx.Graph() de networkx. Luego, agregamos las
conexiones utilizando add_edges_from, donde pasamos una lista de tuplas que representan las
conexiones entre los vértices.

A continuación, generamos las posiciones de los nodos utilizando el algoritmo de spring_layout de


networkx. Esto es necesario para ubicar los nodos en el plano.

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 18

Finalmente, utilizamos nx.draw para dibujar el grafo con las posiciones y opciones de estilo específicas.
with_labels=True muestra los números de los nodos, node_size define el tamaño de los nodos,
node_color establece el color de los nodos, font_size define el tamaño de la fuente y edge_color
establece el color de las conexiones.

Captura de ejecución

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 19

Tarea
• Encontrar los nodos a una distancia dada: Escribe una función que tome un grafo y un nodo de
inicio, y encuentre todos los nodos que están a una distancia dada (por ejemplo, 2) desde el
nodo de inicio. Imprime los nodos encontrados.
import networkx as nx

def find_nodes_at_distance(graph, start_node, distance):


nodes_at_distance = []
for node in graph.nodes():
if node != start_node and nx.shortest_path_length(graph,
start_node, node) == distance:
nodes_at_distance.append(node)
return nodes_at_distance

# Ejemplo de uso
G = nx.Graph()
G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1)])

start_node = 1
distance = 2
nodes_at_distance = find_nodes_at_distance(G, start_node, distance)
print("Nodos a una distancia de", distance, "desde el nodo", start_node,
":", nodes_at_distance)

• Verificar si un grafo es conexo: Escribe una función que tome un grafo como entrada y verifique
si el grafo es conexo. Un grafo es conexo si existe un camino entre cualquier par de nodos.
import networkx as nx

def is_connected(graph):
return nx.is_connected(graph)

# Ejemplo de uso
G = nx.Graph()
G.add_edges_from([(1, 2), (2, 3), (3, 1)])

if is_connected(G):
print("El grafo es conexo.")
else:
print("El grafo no es conexo.")

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 20

• Encontrar el camino más corto: Escribe una función que tome un grafo y dos nodos como
entrada, y encuentre el camino más corto entre los dos nodos utilizando el algoritmo de
Dijkstra. Imprime el camino más corto encontrado.
import networkx as nx

def find_shortest_path(graph, start_node, end_node):


shortest_path = nx.shortest_path(graph, start_node, end_node)
return shortest_path

# Ejemplo de uso
G = nx.Graph()
G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 5)])

start_node = 1
end_node = 5
shortest_path = find_shortest_path(G, start_node, end_node)
print("Camino más corto entre el nodo", start_node, "y el nodo", end_node,
":", shortest_path)

• Adjuntar capturas importantes del código


• Adjuntar capturas de la prueba del código, así como de su ejecución
• Adjuntar el código en un zip, rar, Google drive o git

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION


Laboratorio de Estructura de Datos y Algoritmos Página | 21

OBSERVACIONES:
1. Los grafos son una estructura de datos utilizada para representar relaciones o conexiones entre
elementos.
2. Los grafos se componen de nodos (vértices) y aristas (arcos) que conectan los nodos.
3. Existen varios tipos de grafos, como grafos dirigidos y no dirigidos, grafos ponderados y grafos
cíclicos o acíclicos.
4. Los grafos tienen muchas aplicaciones prácticas en diversos campos. Por ejemplo, en redes
sociales, los nodos pueden representar usuarios y las aristas las conexiones de amistad. En
logística, los nodos pueden ser ubicaciones y las aristas los caminos entre ellas.
5. Los grafos plantean una variedad de problemas y desafíos algorítmicos interesantes.

CONCLUSIONES:
1. Los grafos son una estructura de datos versátil y poderosa que permite representar y analizar
una amplia gama de relaciones y conexiones en diversos contextos.
2. Los grafos ofrecen una forma abstracta de modelar relaciones y conexiones, lo que permite
simplificar y comprender mejor problemas complejos.
3. Existen numerosos algoritmos y técnicas diseñados específicamente para trabajar con grafos, lo
que permite resolver problemas de manera eficiente.
4. Los grafos son especialmente útiles para modelar sistemas complejos, donde múltiples
elementos interactúan entre sí.
5. los grafos pueden parecer abstractos a primera vista, tienen muchas aplicaciones prácticas en la
vida cotidiana.

DEPARTAMENTO DE TECNOLOGIA DIGITAL Y GESTION

También podría gustarte