Skip to content

Commit

Permalink
sciprog draw_nx options, graph equidistances
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidLeoni committed Nov 19, 2019
1 parent 89feb47 commit b161a47
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 52 deletions.
137 changes: 111 additions & 26 deletions exercises/graph-algos/graph-algos.ipynb

Large diffs are not rendered by default.

22 changes: 20 additions & 2 deletions exercises/graph-algos/graph_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def distances(self, source):
Source has distance zero from itself
Verteces immediately connected to source have distance one.
if source is not a vertex, raises an Exception
- if source is not a vertex, raises an LookupError
HINT: implement this using bfs search.
"""
Expand All @@ -328,7 +328,7 @@ def distances(self, source):
# respect to the source

if not source in self.verteces():
raise Exception("Can't find vertex:" + str(source))
raise LookupError("Can't find vertex:" + str(source))

Q = deque()
# we start from source
Expand Down Expand Up @@ -533,6 +533,24 @@ def topSortRec(u, visited, S):
return S
#/jupman-raise

def equidistances(self, va, vb):
""" RETURN a dictionary holding the nodes which
are equidistant from input verteces va and vb.
The dictionary values will be the distances of the nodes.
- if va or vb are not present in the graph, raises LookupError
- To implement this, you can use the previously defined distances() method
"""
#jupman-raise

da = self.distances(va)
db = self.distances(vb)
ret = {}
for v in da:
if da[v] != -1 and da[v] == db[v]:
ret[v] = da[v]
return ret
#/jupman-raise

def full_graph(verteces):
""" Returns a DiGraph which is a full graph with provided verteces list.
Expand Down
70 changes: 70 additions & 0 deletions exercises/graph-algos/graph_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,76 @@ def test_07_square(self):
'c': 1,
'd': 2})

class EquiDistancesTest(DiGraphTest):

def test_01_empty(self):
with self.assertRaises(LookupError):
dig({}).equidistances('a','a')

with self.assertRaises(LookupError):
dig({}).equidistances('a','b')


def test_02_not_found(self):
with self.assertRaises(Exception):
dig({'a'}).equidistances('a','b')


def test_03_root(self):
self.assertEqual(dig({'a': []}).equidistances('a','a'),
{'a':0})

def test_03_root_self(self):
self.assertEqual(dig({'a': ['a']}).equidistances('a','a'),
{'a': 0})


def test_04_ab_no_selfloops(self):
self.assertEqual(dig({'a': ['b'],
'b': ['a']}).equidistances('a','b'),
{})

def test_05_ab_unreachable(self):
self.assertEqual(dig({'a': [],
'b': []}).equidistances('a', 'b'),
{})


def test_06_a_b_c(self):
self.assertEqual(dig({'a': ['b'],
'b': [],
'c': ['b']}).equidistances('a','c'),
{'b': 1})

def test_06_a_b_c_d_e(self):
self.assertEqual(dig({'a': ['b'],
'b': ['c'],
'c': [],
'd':['c'],
'e': ['d'],
}).equidistances('a','e'),
{'c': 2})


def test_06_diamond(self):
self.assertEqual(dig({'a': ['b','c'],
'd': ['b','c']}).equidistances('a','d'),
{'b': 1,
'c': 1})


def test_07_complex(self):
self.assertEqual(dig({ 'a': ['b','e'],
'b': ['d'],
'c': ['d'],
'd': ['f'],
'e': ['d','b'],
'f': ['g','h'],
'g': ['e']}).equidistances('a','g'),
{'d': 2,
'e': 1,
'f': 3,
'h': 4})

class CpTest(DiGraphTest):

Expand Down
25 changes: 15 additions & 10 deletions exercises/sorting/sorting.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,27 @@
"\n",
"[Browse files online](https://github.com/DavidLeoni/datasciprolab/tree/master/exercises/sorting)\n",
"\n",
"## What to do\n",
"## Introduction\n",
"\n",
"### References\n",
"\n",
"- [Alberto Montresor Algorithm analysis slides](http://disi.unitn.it/~montreso/sp/handouts/B01-analisi.pdf)\n",
"- [Python DS Chapter 2.6: Algorithm analysis](https://runestone.academy/runestone/books/published/pythonds/AlgorithmAnalysis/toctree.html)\n",
"\n",
"### What to do\n",
"\n",
"- unzip exercises in a folder, you should get something like this: \n",
"\n",
"```\n",
"\n",
"-jupman.py\n",
"-sciprog.py\n",
"-other stuff ...\n",
"-exercises\n",
" |-sorting\n",
" |- sorting.ipynb \n",
" |- selection_sort_exercise.py \n",
" |- selection_sort_test.py\n",
" |- selection_sort_solution.py \n",
" |- other stuff ..\n",
"```\n",
"\n",
"\n",
Expand Down Expand Up @@ -616,7 +621,7 @@
{
"data": {
"text/plain": [
"<list_reverseiterator at 0x7f0cac14aa20>"
"<list_reverseiterator at 0x7f39b0ba43c8>"
]
},
"execution_count": 10,
Expand Down Expand Up @@ -1748,32 +1753,32 @@
"text": [
"...............\n",
"----------------------------------------------------------------------\n",
"Ran 15 tests in 0.008s\n",
"Ran 15 tests in 0.012s\n",
"\n",
"OK\n",
"......\n",
"----------------------------------------------------------------------\n",
"Ran 6 tests in 0.002s\n",
"Ran 6 tests in 0.005s\n",
"\n",
"OK\n",
"..............\n",
"----------------------------------------------------------------------\n",
"Ran 14 tests in 0.006s\n",
"Ran 14 tests in 0.010s\n",
"\n",
"OK\n",
".................\n",
"----------------------------------------------------------------------\n",
"Ran 17 tests in 0.008s\n",
"Ran 17 tests in 0.009s\n",
"\n",
"OK\n",
".................\n",
"----------------------------------------------------------------------\n",
"Ran 17 tests in 0.007s\n",
"Ran 17 tests in 0.012s\n",
"\n",
"OK\n",
"...............................\n",
"----------------------------------------------------------------------\n",
"Ran 31 tests in 0.012s\n",
"Ran 31 tests in 0.019s\n",
"\n",
"OK\n"
]
Expand Down
36 changes: 22 additions & 14 deletions sciprog.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
# Library of utilities for
# Scientific Programming
# Data Science Master @Unitn
# author: David Leoni
#
# DO NOT MODIFY THIS FILE !
#
#
#
#

import unittest
import sys
Expand All @@ -22,22 +24,22 @@ def show_distances():
('f -1', 'g -1')])
return ret

def dig_to_nx(algolab_digraph):
""" Convert an Algolab DiGraph into a NetworkX graph and return it. """
def dig_to_nx(sciprog_digraph):
""" Convert a Sciprog DiGraph into a NetworkX graph and return it. """
import networkx as nx

ret = nx.DiGraph()
ret.graph['dpi'] = 80
ret.add_nodes_from(algolab_digraph.verteces())
for sv in algolab_digraph.verteces():
for tv in algolab_digraph.adj(sv):
ret.add_nodes_from(sciprog_digraph.verteces())
for sv in sciprog_digraph.verteces():
for tv in sciprog_digraph.adj(sv):
ret.add_edge(sv, tv)
return ret

def draw_dig(sciprog_digraph,legend_edges=None, label='', save_to=''):
def draw_dig(sciprog_digraph,legend_edges=None, label='', save_to='', options={}):
""" Draws a Sciprog DiGraph"""

draw_nx(dig_to_nx(sciprog_digraph),legend_edges, label=label, save_to=save_to)
draw_nx(dig_to_nx(sciprog_digraph),legend_edges, label=label, save_to=save_to, options=options)


def get_pydot_mod(obj):
Expand All @@ -56,7 +58,7 @@ def get_pydot_mod(obj):



def draw_nx(G, legend_edges=None, label='', save_to=''):
def draw_nx(G, legend_edges=None, label='', save_to='', options={}):
""" Draws a NetworkX graph object. By default, assumes it is a DiGraph.
Optionally, saves it as .png image to filepath save_to
Expand Down Expand Up @@ -113,11 +115,17 @@ def merge(d2, d1):


# add graphviz layout options (see https://stackoverflow.com/a/39662097)
if 'node' in options:
merge(G.graph['node'], options['node'])
if 'edge' in options:
merge(G.graph['edge'], options['edge'])
if 'graph' in options:
merge(G.graph['graph'], options['graph'])

merge(G.graph['node'], {'color':'blue', 'fontcolor':'blue'})
merge(G.graph['edge'], {'arrowsize': '0.6', 'splines': 'curved', 'fontcolor':'brown'})
merge(G.graph['graph'], {'scale': '3'}) #

# adding attributes to edges in multigraphs is more complicated but see
# https://stackoverflow.com/a/26694158
#G[0][0]['color']='red'
Expand Down Expand Up @@ -168,7 +176,7 @@ def make_legend():
print(e)


def draw_mat(mat, legend_edges=None, label='', save_to=''):
def draw_mat(mat, legend_edges=None, label='', save_to='', options={}):
""" Draws a matrix as a DiGraph
Optionally, saves it as .png image to filepath save_to
Expand Down Expand Up @@ -198,9 +206,9 @@ def draw_mat(mat, legend_edges=None, label='', save_to=''):



draw_nx(G,legend_edges, label=label, save_to=save_to)
draw_nx(G,legend_edges, label=label, save_to=save_to, options=options)

def draw_adj(d,legend_edges=None, label='', save_to=''):
def draw_adj(d,legend_edges=None, label='', save_to='', options={}):
"""
Draws a a graph represented as a dictionary of adjancency lists.
Node identifiers can be any immutable data structure, like numbers, strings, tuples ...
Expand All @@ -226,7 +234,7 @@ def draw_adj(d,legend_edges=None, label='', save_to=''):
import networkx as nx

G=nx.DiGraph(d)
draw_nx(G,legend_edges, label=label, save_to=save_to)
draw_nx(G,legend_edges, label=label, save_to=save_to, options=options)


def draw_proof(proof, db, step_id=None, only_ids=False):
Expand Down
11 changes: 11 additions & 0 deletions slides.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,17 @@
"Remember that from now on we only use Visual Studio Code"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Lab B.3\n",
"\n",
"Tuesday 19 November\n",
"\n",
"* [Sorting](exercises/sorting/sorting.ipynb) \n"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down

0 comments on commit b161a47

Please sign in to comment.