feat: 🔥 Remove debug.py and add it to gitignore
This commit is contained in:
parent
6910cd1f76
commit
e2150ca078
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
.idea
|
.idea
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/.idea
|
/.idea
|
||||||
|
debug.py
|
446
debug.py
446
debug.py
@ -1,446 +0,0 @@
|
|||||||
import queue
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""Graph module.
|
|
||||||
|
|
||||||
Provide an implementation of graphs with adjacency lists.
|
|
||||||
|
|
||||||
In a graph, vertices are considered numbered from 0 to the order of the graph
|
|
||||||
minus one. The vertex key can then be used to access its
|
|
||||||
adjacency list.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class Graph:
|
|
||||||
""" Simple class for graph: adjacency lists
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
order (int): Number of vertices.
|
|
||||||
directed (bool): True if the graph is directed. False otherwise.
|
|
||||||
adjlists (List[List[int]]): Lists of connected vertices for each vertex.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, order, directed, labels=None):
|
|
||||||
"""Init graph, allocate adjacency lists
|
|
||||||
|
|
||||||
Args:
|
|
||||||
order (int): Number of nodes.
|
|
||||||
directed (bool): True if the graph is directed. False otherwise.
|
|
||||||
labels (list[str]): optionnal vector of vertex labels
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.order = order
|
|
||||||
self.directed = directed
|
|
||||||
self.adjlists = []
|
|
||||||
for _ in range(order):
|
|
||||||
self.adjlists.append([])
|
|
||||||
self.labels = labels
|
|
||||||
|
|
||||||
def addedge(self, src, dst):
|
|
||||||
"""Add egde to graph.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
src (int): Source vertex.
|
|
||||||
dst (int): Destination vertex.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
IndexError: If any vertex index is invalid.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if src >= self.order or src < 0:
|
|
||||||
raise IndexError("Invalid src index")
|
|
||||||
if dst >= self.order or dst < 0:
|
|
||||||
raise IndexError("Invalid dst index")
|
|
||||||
|
|
||||||
self.adjlists[src].append(dst)
|
|
||||||
if not self.directed and dst != src:
|
|
||||||
self.adjlists[dst].append(src)
|
|
||||||
|
|
||||||
|
|
||||||
def addvertex(self, number=1, labels=None):
|
|
||||||
"""Add number vertices to graph.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ref (Graph).
|
|
||||||
number (int): Number of vertices to add.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Increment order and extend adjacency list
|
|
||||||
self.order += number
|
|
||||||
for _ in range(number):
|
|
||||||
self.adjlists.append([])
|
|
||||||
if labels:
|
|
||||||
self.labels += labels
|
|
||||||
|
|
||||||
def removeedge(self, src, dst):
|
|
||||||
"""Remove egde from the graph.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
src (int): Source vertex.
|
|
||||||
dst (int): Destination vertex.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
IndexError: If any vertex index is invalid.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if src >= self.order or src < 0:
|
|
||||||
raise IndexError("Invalid src index")
|
|
||||||
if dst >= self.order or dst < 0:
|
|
||||||
raise IndexError("Invalid dst index")
|
|
||||||
if dst in self.adjlists[src]:
|
|
||||||
self.adjlists[src].remove(dst)
|
|
||||||
if not self.directed and dst != src:
|
|
||||||
self.adjlists[dst].remove(src)
|
|
||||||
|
|
||||||
def sortgraph(G):
|
|
||||||
"""
|
|
||||||
sorts adjacency lists -> to have same results as those asked in tutorials/exams
|
|
||||||
"""
|
|
||||||
for i in range(G.order):
|
|
||||||
G.adjlists[i].sort()
|
|
||||||
|
|
||||||
def dot(G):
|
|
||||||
"""Dot format of graph.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
Graph
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: String storing dot format of graph.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if G.directed:
|
|
||||||
s = "digraph {\n"
|
|
||||||
for x in range(G.order):
|
|
||||||
if G.labels:
|
|
||||||
s += " " + str(x) + '[label = "' + G.labels[x] + '"]\n'
|
|
||||||
else:
|
|
||||||
s += " " + str(x) + '\n'
|
|
||||||
for y in G.adjlists[x]:
|
|
||||||
s += str(x) + " -> " + str(y) + '\n'
|
|
||||||
else:
|
|
||||||
s = "graph {\n"
|
|
||||||
for x in range(G.order):
|
|
||||||
if G.labels:
|
|
||||||
s += " " + str(x) + '[label = "' + G.labels[x] + '"]\n'
|
|
||||||
else:
|
|
||||||
s += " " + str(x) + '\n'
|
|
||||||
for y in G.adjlists[x]:
|
|
||||||
if x <= y:
|
|
||||||
s += str(x) + " -- " + str(y) + '\n'
|
|
||||||
return s + '}'
|
|
||||||
|
|
||||||
def display(G, eng=None):
|
|
||||||
"""
|
|
||||||
*Warning:* Made for use within IPython/Jupyter only.
|
|
||||||
eng: graphivz.Source "engine" optional argument (try "neato", "fdp", "sfdp", "circo")
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
from graphviz import Source
|
|
||||||
from IPython.display import display
|
|
||||||
except:
|
|
||||||
raise Exception("Missing module: graphviz and/or IPython.")
|
|
||||||
display(Source(dot(G), engine = eng))
|
|
||||||
|
|
||||||
|
|
||||||
# load / save gra format
|
|
||||||
|
|
||||||
def load(filename):
|
|
||||||
"""Build a new graph from a GRA file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
filename (str): File to load.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Graph: New graph.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FileNotFoundError: If file does not exist.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
f = open(filename)
|
|
||||||
lines = f.readlines()
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
infos = {}
|
|
||||||
i = 0
|
|
||||||
while '#' in lines[i]:
|
|
||||||
(key, val) = lines[i][1:].strip().split(": ")
|
|
||||||
infos[key] = val
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
directed = bool(int(lines[i]))
|
|
||||||
order = int(lines[i+1])
|
|
||||||
|
|
||||||
if infos and "labels" in infos:
|
|
||||||
labels = infos["labels"].split(',') #labels is a list of str
|
|
||||||
G = Graph(order, directed, labels) # a graph with labels
|
|
||||||
else:
|
|
||||||
G = Graph(order, directed) # a graph without labels
|
|
||||||
if infos:
|
|
||||||
G.infos = infos
|
|
||||||
|
|
||||||
for line in lines[i+2:]:
|
|
||||||
edge = line.strip().split(' ')
|
|
||||||
(src, dst) = (int(edge[0]), int(edge[1]))
|
|
||||||
G.addedge(src, dst)
|
|
||||||
return G
|
|
||||||
|
|
||||||
|
|
||||||
def save(G, fileOut):
|
|
||||||
gra = ""
|
|
||||||
if G.labels:
|
|
||||||
lab = "#labels: "
|
|
||||||
for i in range(G.order - 1):
|
|
||||||
lab += G.labels[i] + ','
|
|
||||||
lab += G.labels[-1]
|
|
||||||
gra += lab + '\n'
|
|
||||||
gra += str(int(G.directed)) + '\n'
|
|
||||||
gra += str(G.order) + '\n'
|
|
||||||
for x in range(G.order):
|
|
||||||
for y in G.adjlists[x]:
|
|
||||||
if G.directed or x >= y:
|
|
||||||
gra += str(x) + " " + str(y) + '\n'
|
|
||||||
fout = open(fileOut, mode='w')
|
|
||||||
fout.write(gra)
|
|
||||||
fout.close()
|
|
||||||
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""Graph module.
|
|
||||||
|
|
||||||
Provide an implementation of graphs with adjacency matrix.
|
|
||||||
This can also be called static implementation.
|
|
||||||
|
|
||||||
In a graph, vertices are considered numbered from 0 to the order of the graph
|
|
||||||
minus one.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class GraphMat:
|
|
||||||
""" Simple class for static graph.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
order (int): Number of vertices.
|
|
||||||
directed (bool): True if the graph is directed. False otherwise.
|
|
||||||
adj (List[List[int]]): Adjacency matrix
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, order, directed):
|
|
||||||
"""
|
|
||||||
Args:
|
|
||||||
order (int): Number of nodes.
|
|
||||||
directed (bool): True if the graph is directed. False otherwise.
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.order = order
|
|
||||||
self.directed = directed
|
|
||||||
self.adj = [[0 for j in range(order)] for i in range(order)]
|
|
||||||
|
|
||||||
|
|
||||||
def addedge(self, src, dst):
|
|
||||||
"""Add egde to graph.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
src (int): Source vertex.
|
|
||||||
dst (int): Destination vertex.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
IndexError: If any vertex index is invalid.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if src >= self.order or src < 0:
|
|
||||||
raise IndexError("Invalid src index")
|
|
||||||
if dst >= self.order or dst < 0:
|
|
||||||
raise IndexError("Invalid dst index")
|
|
||||||
|
|
||||||
self.adj[src][dst] += 1
|
|
||||||
if not self.directed and dst != src:
|
|
||||||
self.adj[dst][src] += 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def dot(G):
|
|
||||||
"""Dot format of graph.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
GraphMat
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: String storing dot format of graph.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if G.directed:
|
|
||||||
s = "digraph {\n"
|
|
||||||
link = " -> "
|
|
||||||
for x in range(G.order):
|
|
||||||
for y in range(G.order):
|
|
||||||
s += (str(x) + link + str(y) + '\n') * G.adj[x][y]
|
|
||||||
else:
|
|
||||||
s = "graph {\n"
|
|
||||||
link = " -- "
|
|
||||||
for x in range(G.order):
|
|
||||||
for y in range(x+1):
|
|
||||||
s += (str(x) + link + str(y) + '\n') * G.adj[x][y]
|
|
||||||
return s + '}'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def display(G, eng=None):
|
|
||||||
"""
|
|
||||||
*Warning:* Made for use within IPython/Jupyter only.
|
|
||||||
eng: graphivz.Source "engine" optional argument (try "neato", "fdp", "sfdp", "circo")
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
from graphviz import Source
|
|
||||||
from IPython.display import display
|
|
||||||
except:
|
|
||||||
raise Exception("Missing module: graphviz and/or IPython.")
|
|
||||||
display(Source(dot(G), engine = eng))
|
|
||||||
|
|
||||||
|
|
||||||
# load / save gra format (do not manage labels and other infos)
|
|
||||||
|
|
||||||
def load(filename,):
|
|
||||||
"""Build a new graph from a GRA file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
filename (str): File to load.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Graph: New graph.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FileNotFoundError: If file does not exist.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
f = open(filename)
|
|
||||||
directed = bool(int(f.readline()))
|
|
||||||
order = int(f.readline())
|
|
||||||
g = GraphMat(order, directed)
|
|
||||||
for line in f.readlines():
|
|
||||||
edge = line.strip().split(' ')
|
|
||||||
(src, dst) = (int(edge[0]), int(edge[1]))
|
|
||||||
g.addedge(src, dst)
|
|
||||||
f.close()
|
|
||||||
return g
|
|
||||||
|
|
||||||
def save(G, fileOut):
|
|
||||||
gra = str(int(G.directed)) + '\n'
|
|
||||||
gra += str(G.order) + '\n'
|
|
||||||
for x in range(G.order):
|
|
||||||
if G.directed:
|
|
||||||
n = G.order
|
|
||||||
else:
|
|
||||||
n = x + 1
|
|
||||||
for y in range(n):
|
|
||||||
for i in range(G.adj[x][y]):
|
|
||||||
gra += str(x) + " " + str(y) + '\n'
|
|
||||||
fout = open(fileOut, mode='w')
|
|
||||||
fout.write(gra)
|
|
||||||
fout.close()
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""Queue module."""
|
|
||||||
|
|
||||||
from collections import deque
|
|
||||||
|
|
||||||
class Queue:
|
|
||||||
"""Simple class for FIFO (first-in-first-out) container."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Init queue."""
|
|
||||||
|
|
||||||
self.elements = deque()
|
|
||||||
|
|
||||||
def enqueue(self, elt):
|
|
||||||
"""Add an element to the queue.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
elt (Any): Element to enqueue.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.elements.append(elt)
|
|
||||||
|
|
||||||
def dequeue(self):
|
|
||||||
"""Remove and return next element from the queue.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Any: Element from the queue.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
IndexError: If queue is empty.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.elements.popleft()
|
|
||||||
|
|
||||||
def isempty(self):
|
|
||||||
"""Check whether queue is empty.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if queue is empty, False otherwise.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
return len(self.elements) == 0
|
|
||||||
|
|
||||||
G = Graph(10, False)
|
|
||||||
G.adjlists = [[4, 4, 1, 3],
|
|
||||||
[0],
|
|
||||||
[6, 6, 6, 5, 7],
|
|
||||||
[0],
|
|
||||||
[0, 0, 9],
|
|
||||||
[2, 7, 8],
|
|
||||||
[2, 2, 2, 7],
|
|
||||||
[2, 6, 5, 8],
|
|
||||||
[7, 5, 8],
|
|
||||||
[4]]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __smallest_level(G, M, src, perLevel):
|
|
||||||
cur = Queue()
|
|
||||||
cur.enqueue(src)
|
|
||||||
cur.enqueue(None)
|
|
||||||
M[src] = True
|
|
||||||
temp = []
|
|
||||||
while not cur.isempty():
|
|
||||||
x = cur.dequeue()
|
|
||||||
if x is None:
|
|
||||||
if (len(temp) != 0 and temp != [src]):
|
|
||||||
perLevel.append(temp)
|
|
||||||
temp = []
|
|
||||||
else:
|
|
||||||
temp.append(x)
|
|
||||||
for adj in G.adjlists[x]:
|
|
||||||
if not M[adj]:
|
|
||||||
M[adj] = True
|
|
||||||
cur.enqueue(adj)
|
|
||||||
cur.enqueue(None)
|
|
||||||
def smallest_level(G, src):
|
|
||||||
M = [False] * G.order
|
|
||||||
perLevel = []
|
|
||||||
__smallest_level(G, M, src, perLevel)
|
|
||||||
min = perLevel[0]
|
|
||||||
for element in perLevel:
|
|
||||||
if len(element) < len(min):
|
|
||||||
min = element
|
|
||||||
return min
|
|
||||||
|
|
||||||
smallest_level(G, 0)
|
|
Loading…
x
Reference in New Issue
Block a user