Source code for graphs

# -*- coding: utf-8 -*-
"""**Graph support**

Basic Graph object support and manipulation

.. versionadded: 1.0

.. *Authors:* Rogério Reis & Nelma Moreira

.. *This is part of FAdo project*   http://fado.dcc.fc.up.pt.

.. *Copyright:* 2014 Rogério Reis & Nelma Moreira {rvr,nam}@dcc.fc.up.pt

.. This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as published
   by the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   675 Mass Ave, Cambridge, MA 02139, USA."""

import copy

from common import *


[docs]class Graph(Drawable): """Graph base class :var list Vertices: Vertices' names :var set Edges: set of pairs (always sorted) .. inheritance-diagram:: Graph"""
[docs] @abstractmethod def dotFormat(self, size): pass
def __init__(self): self.Vertices = [] self.Edges = set()
[docs] def addVertex(self, vname): """Adds a vertex (by name) :param vname: vertex name :return: vertex index :rtype: int :raises DuplicateName: if vname already exists""" if vname in self.Vertices: raise DuplicateName self.Vertices.append(vname) return len(self.Vertices) - 1
[docs] def vertexIndex(self, vname, autoCreate=False): """Return vertex index :param bool autoCreate: auto creation of non existing states :param vname: vertex name :rtype: int :raises GraphError: if vname not found""" if vname not in self.Vertices: if not autoCreate: raise GraphError else: return self.addVertex(vname) else: return self.Vertices.index(vname)
[docs] def addEdge(self, v1, v2): """Adds an edge :param int v1: vertex 1 index :param int v2: vertex 2 index :raises GraphError: if edge is loop""" if v1 == v2: raise GraphError if v1 < v2: self.Edges.add((v1, v2)) else: self.Edges.add((v2, v1))
[docs]class DiGraph(Graph): """Directed graph base class .. inheritance-diagram:: DiGraph"""
[docs] def addEdge(self, v1, v2): """Adds an edge :param int v1: vertex 1 index :param int v2: vertex 2 index""" self.Edges.add((v1, v2))
[docs] def inverse(self): """Inverse of a digraph""" new = DiGraph() new.Vertices = copy.deepcopy(self.Vertices) for (i, j) in self.Edges: new.addVertex(j) return new
# noinspection PyUnresolvedReferences
[docs] def dotFormat(self, size="20,20", direction="LR", sep="\n", strict=False, maxLblSz=MAXLBL): """ A dot representation :arg str direction: direction of drawing :arg str size: size of image :arg str sep: line separator :arg maxLblSz: max size of labels before getting removed :arg strict: use limitations of label sizes :return: the dot representation :rtype: str .. versionadded:: 0.9.6 .. versionchanged:: 0.9.8""" s = "digraph finite_state_machine {{{0:s}".format(sep) s += "rankdir={0:s};{1:s}".format(direction, sep) s += "size=\"{0:s}\";{1:s}".format(size, sep) s += "node [shape = point]; dummy{0:s}".format(sep) niStates = [i for i in range(len(self.States)) if i != self.Initial] for sti in niStates: s += self.dotDrawVertex(sti) for s1, s2 in self.Edges: s += self.dotDrawEdge(s1, s2) s += "}}{0:s}".format(sep) return s
[docs] @staticmethod def dotDrawEdge(st1, st2, sep="\n"): """ Draw a transition in Dot Format :arg str st1: starting state :arg str st2: ending state :arg str sep: separator :rtype: str""" return "\"{0:s}\" -> \"{1:s}\" {3:s} ".format(st1, st2, sep)
[docs] def dotDrawVertex(self, sti, sep="\n"): """ Draw a Vertex in Dot Format :arg int sti: index of the state :arg str sep: separator :rtype: str """ lbl = self.Vertices[sti].__str__() return "node [shape = circle]; \"{0:s}\";{1:s}".format(lbl, sep)
[docs]class DiGraphVm(DiGraph): """Directed graph with marked vertices :var set MarkedV: set of marked vertices .. inheritance-diagram:: DiGraphVm""" def __init__(self): super(DiGraphVm, self).__init__() self.MarkedV = set()
[docs] def markVertex(self, v): """Mark vertex v :param int v: vertex""" self.MarkedV.add(v)