Ticket #12626: trac_12626_kautz_digraph_generator.patch

File trac_12626_kautz_digraph_generator.patch, 14.2 KB (added by dcoudert, 8 years ago)
  • sage/graphs/digraph_generators.py

    # HG changeset patch
    # User dcoudert <david.coudert@inria.fr>
    # Date 1330806160 -3600
    # Node ID 383a9770116de3584bc677a209ee2374729d4e5c
    # Parent  218094b2e56274dae1c8cf21bb191d2cc5ab7b44
    trac #12626 -- Kautz, ImaseItoh, and GeneralizedDeBruijn digraphs generators
    
    diff --git a/sage/graphs/digraph_generators.py b/sage/graphs/digraph_generators.py
    a b  
    4747
    4848                Families of Graphs:
    4949                    - DeBruijn
     50                    - GeneralizedDeBruijn
     51                    - Kautz
     52                    - ImaseItoh
    5053
    5154           
    5255   
     
    287290            g.add_edge(n-1,0)
    288291            return g       
    289292
    290     def DeBruijn(self,k,n):
     293    def DeBruijn(self, k, n, vertices = 'strings'):
    291294        r"""
    292295        Returns the De Bruijn diraph with parameters `k,n`.
    293296
    294         The De Bruijn digraph with parameters `k,n` is built
    295         upon a set of vertices equal to the set of words of
    296         length `n` from a dictionary of `k` letters.
     297        The De Bruijn digraph with parameters `k,n` is built upon a set of
     298        vertices equal to the set of words of length `n` from a dictionary of
     299        `k` letters.
    297300
    298         In this digraph, there is an arc `w_1w_2` if `w_2`
    299         can be obtained from `w_1` by removing the leftmost
    300         letter and adding a new letter at its right end.
    301         For more information, see the
    302         `Wikipedia article on De Bruijn graph
    303         <http://en.wikipedia.org/wiki/De_Bruijn_graph>`_.
     301        In this digraph, there is an arc `w_1w_2` if `w_2` can be obtained from
     302        `w_1` by removing the leftmost letter and adding a new letter at its
     303        right end.  For more information, see the
     304        :wikipedia:`Wikipedia article on De Bruijn graph <De_Bruijn_graph>`.
    304305
    305306        INPUT:
    306307
    307308        - ``k`` -- Two possibilities for this parameter :
    308               - an integer equal to the cardinality of the
    309                 alphabet to use.
    310               - An iterable object to be used as the set
    311                 of letters
    312         - ``n`` -- An integer equal to the length of words in
    313           the De Bruijn digraph.
     309              - An integer equal to the cardinality of the alphabet to use, that
     310                is the degree of the digraph to be produced.
     311              - An iterable object to be used as the set of letters. The degree
     312                of the resulting digraph is the cardinality of the set of
     313                letters.
     314
     315        - ``n`` -- An integer equal to the length of words in the De Bruijn
     316          digraph when ``vertices == 'strings'``, and also to the diameter of
     317          the digraph.
     318
     319        - ``vertices`` -- 'strings' (default) or 'integers', specifying whether
     320          the vertices are words build upon an alphabet or integers.
    314321
    315322        EXAMPLES::
    316323
     
    327334            De Bruijn digraph (k=5, n=0): Looped multi-digraph on 1 vertex
    328335            sage: digraphs.DeBruijn(0,0)
    329336            De Bruijn digraph (k=0, n=0): Looped multi-digraph on 0 vertices
    330 
    331337        """
    332338        from sage.combinat.words.words import Words
    333339        from sage.rings.integer import Integer
     
    336342        A = Words(range(k) if isinstance(k, Integer) else k, 1)
    337343        g = DiGraph(loops=True)
    338344
    339         if n == 0 :
    340             g.allow_multiple_edges(True)
    341             v = W[0]
    342             for a in A:
    343                 g.add_edge(v.string_rep(), v.string_rep(), a.string_rep())
     345        if vertices == 'strings':
     346            if n == 0 :
     347                g.allow_multiple_edges(True)
     348                v = W[0]
     349                for a in A:
     350                    g.add_edge(v.string_rep(), v.string_rep(), a.string_rep())
     351            else:
     352                for w in W:
     353                    ww = w[1:]
     354                    for a in A:
     355                        g.add_edge(w.string_rep(), (ww*a).string_rep(), a.string_rep())
    344356        else:
    345             for w in W:
    346                 ww = w[1:]
    347                 for a in A:
    348                     g.add_edge(w.string_rep(), (ww*a).string_rep(), a.string_rep())
     357            d = W.size_of_alphabet()
     358            g = digraphs.GeneralizedDeBruijn(d**n, d)
    349359
    350360        g.name( "De Bruijn digraph (k=%s, n=%s)"%(k,n) )
    351361        return g
    352362
     363    def GeneralizedDeBruijn(self, n, d):
     364        r"""
     365        Returns the generalized de Bruijn digraph of order `n` and degree `d`.
     366
     367        The generalized de Bruijn digraph has been defined in [RPK80]_
     368        [RPK83]_. It has vertex set `V=\{0, 1,..., n-1\}` and there is an arc
     369        from vertex `u \in V` to all vertices `v \in V` such that
     370        `v \equiv (u*d + a) \mod{n}` with `0 \leq a < d`.
     371
     372        When `n = d^{D}`, the generalized de Bruijn digraph is isomorphic to the
     373        de Bruijn digraph of degree `d` and diameter `D`.
     374
     375        INPUTS:
     376
     377        - ``n`` -- is the number of vertices of the digraph
     378
     379        - ``d`` -- is the degree of the digraph
     380
     381        EXAMPLE::
     382
     383            sage: GB = digraphs.GeneralizedDeBruijn(8, 2)
     384            sage: GB.is_isomorphic(digraphs.DeBruijn(2, 3), certify = True)
     385            (True, {0: '000', 1: '001', 2: '010', 3: '011', 4: '100', 5: '101', 6: '110', 7: '111'})
     386
     387        TESTS:
     388
     389        An exception is raised when the degree is less than one::
     390
     391            sage: G = digraphs.GeneralizedDeBruijn(2, 0)
     392            Traceback (most recent call last):
     393            ...
     394            ValueError: The generalized de Bruijn digraph is defined for degree at least one.
     395
     396        An exception is raised when the order of the graph is less than one::
     397
     398            sage: G = digraphs.GeneralizedDeBruijn(0, 2)
     399            Traceback (most recent call last):
     400            ...
     401            ValueError: The generalized de Bruijn digraph is defined for at least one vertex.
     402
     403
     404        REFERENCES:
     405
     406        .. [RPK80] S. M. Reddy, D. K. Pradhan, and J. Kuhl. Directed graphs with
     407          minimal diameter and maximal connectivity, School Eng., Oakland Univ.,
     408          Rochester MI, Tech. Rep., July 1980.
     409
     410        .. [RPK83] S. Reddy, P. Raghavan, and J. Kuhl. A Class of Graphs for
     411          Processor Interconnection. *IEEE International Conference on Parallel
     412          Processing*, pages 154-157, Los Alamitos, Ca., USA, August 1983.
     413        """
     414        if n < 1:
     415            raise ValueError("The generalized de Bruijn digraph is defined for at least one vertex.")
     416        if d < 1:
     417            raise ValueError("The generalized de Bruijn digraph is defined for degree at least one.")
     418
     419        GB = DiGraph(loops = True)
     420        GB.allow_multiple_edges(True)
     421        for u in xrange(n):
     422            for a in xrange(u*d, u*d+d):
     423                GB.add_edge(u, a%n)
     424
     425        GB.name( "Generalized de Bruijn digraph (n=%s, d=%s)"%(n,d) )
     426        return GB
     427
     428
     429    def ImaseItoh(self, n, d):
     430        r"""
     431        Returns the digraph of Imase and Itoh of order `n` and degree `d`.
     432
     433        The digraph of Imase and Itoh has been defined in [II83]_. It has vertex
     434        set `V=\{0, 1,..., n-1\}` and there is an arc from vertex `u \in V` to
     435        all vertices `v \in V` such that `v \equiv (-u*d-a-1) \mod{n}` with
     436        `0 \leq a < d`.
     437
     438        When `n = d^{D}`, the digraph of Imase and Itoh is isomorphic to the de
     439        Bruijn digraph of degree `d` and diameter `D`. When `n = d^{D-1}(d+1)`,
     440        the digraph of Imase and Itoh is isomorphic to the Kautz digraph
     441        [Kautz68]_ of degree `d` and diameter `D`.
     442
     443        INPUTS:
     444
     445        - ``n`` -- is the number of vertices of the digraph
     446
     447        - ``d`` -- is the degree of the digraph
     448
     449        EXAMPLES::
     450
     451            sage: II = digraphs.ImaseItoh(8, 2)
     452            sage: II.is_isomorphic(digraphs.DeBruijn(2, 3), certify = True)
     453            (True, {0: '010', 1: '011', 2: '000', 3: '001', 4: '110', 5: '111', 6: '100', 7: '101'})
     454
     455            sage: II = digraphs.ImaseItoh(12, 2)
     456            sage: II.is_isomorphic(digraphs.Kautz(2, 3), certify = True)
     457            (True, {0: '010', 1: '012', 2: '021', 3: '020', 4: '202', 5: '201', 6: '210', 7: '212', 8: '121', 9: '120', 10: '102', 11: '101'})
     458
     459
     460        TESTS:
     461
     462        An exception is raised when the degree is less than one::
     463
     464            sage: G = digraphs.ImaseItoh(2, 0)
     465            Traceback (most recent call last):
     466            ...
     467            ValueError: The digraph of Imase and Itoh is defined for degree at least one.
     468
     469        An exception is raised when the order of the graph is less than two::
     470
     471            sage: G = digraphs.ImaseItoh(1, 2)
     472            Traceback (most recent call last):
     473            ...
     474            ValueError: The digraph of Imase and Itoh is defined for at least two vertices.
     475
     476
     477        REFERENCE:
     478
     479        .. [II83] M. Imase and M. Itoh. A design for directed graphs with
     480          minimum diameter, *IEEE Trans. Comput.*, vol. C-32, pp. 782-784, 1983.
     481        """
     482        if n < 2:
     483            raise ValueError("The digraph of Imase and Itoh is defined for at least two vertices.")
     484        if d < 1:
     485            raise ValueError("The digraph of Imase and Itoh is defined for degree at least one.")
     486
     487        II = DiGraph(loops = True)
     488        II.allow_multiple_edges(True)
     489        for u in xrange(n):
     490            for a in xrange(-u*d-d, -u*d):
     491                II.add_edge(u, a % n)
     492
     493        II.name( "Imase and Itoh digraph (n=%s, d=%s)"%(n,d) )
     494        return II
     495
     496
     497    def Kautz(self, k, D, vertices = 'strings'):
     498        r"""
     499        Returns the Kautz digraph of degree `d` and diameter `D`.
     500
     501        The Kautz digraph has been defined in [Kautz68]_. The Kautz digraph of
     502        degree `d` and diameter `D` has `d^{D-1}(d+1)` vertices. This digraph is
     503        build upon a set of vertices equal to the set of words of length `D`
     504        from an alphabet of `d+1` letters such that consecutive letters are
     505        differents. There is an arc from vertex `u` to vertex `v` if `v` can be
     506        obtained from `u` by removing the leftmost letter and adding a new
     507        letter, distinct from the rightmost letter of `u`, at the right end.
     508
     509        The Kautz digraph of degree `d` and diameter `D` is isomorphic to the
     510        digraph of Imase and Itoh [II83]_ of degree `d` and order
     511        `d^{D-1}(d+1)`.
     512
     513        See also the
     514        :wikipedia:`Wikipedia article on Kautz Graphs <Kautz_graph>`.
     515
     516        INPUTS:
     517
     518        - ``k`` -- Two possibilities for this parameter :
     519            - An integer equal to the degree of the digraph to be produced, that
     520              is the cardinality minus one of the alphabet to use.
     521            - An iterable object to be used as the set of letters. The degree of
     522              the resulting digraph is the cardinality of the set of letters
     523              minus one.
     524
     525        - ``D`` -- An integer equal to the diameter of the digraph, and also to
     526              the length of a vertex label when ``vertices == 'strings'``.
     527
     528        - ``vertices`` -- 'strings' (default) or 'integers', specifying whether
     529                      the vertices are words build upon an alphabet or integers.
     530
     531
     532        EXAMPLES::
     533
     534            sage: K = digraphs.Kautz(2, 3)
     535            sage: K.is_isomorphic(digraphs.ImaseItoh(12, 2), certify = True)
     536            (True, {'201': 5, '120': 9, '202': 4, '212': 7, '210': 6, '010': 0, '121': 8, '012': 1, '021': 2, '020': 3, '102': 10, '101': 11})
     537
     538            sage: K = digraphs.Kautz([1,'a','B'], 2)
     539            sage: K.edges()
     540            [('1B', 'B1', '1'), ('1B', 'Ba', 'a'), ('1a', 'a1', '1'), ('1a', 'aB', 'B'), ('B1', '1B', 'B'), ('B1', '1a', 'a'), ('Ba', 'a1', '1'), ('Ba', 'aB', 'B'), ('a1', '1B', 'B'), ('a1', '1a', 'a'), ('aB', 'B1', '1'), ('aB', 'Ba', 'a')]
     541
     542            sage: K = digraphs.Kautz([1,'aA','BB'], 2)
     543            sage: K.edges()
     544            [('1,BB', 'BB,1', '1'), ('1,BB', 'BB,aA', 'aA'), ('1,aA', 'aA,1', '1'), ('1,aA', 'aA,BB', 'BB'), ('BB,1', '1,BB', 'BB'), ('BB,1', '1,aA', 'aA'), ('BB,aA', 'aA,1', '1'), ('BB,aA', 'aA,BB', 'BB'), ('aA,1', '1,BB', 'BB'), ('aA,1', '1,aA', 'aA'), ('aA,BB', 'BB,1', '1'), ('aA,BB', 'BB,aA', 'aA')]
     545
     546
     547        TESTS:
     548
     549        An exception is raised when the degree is less than one::
     550
     551            sage: G = digraphs.Kautz(0, 2)
     552            Traceback (most recent call last):
     553            ...
     554            ValueError: Kautz digraphs are defined for degree at least one.
     555
     556            sage: G = digraphs.Kautz(['a'], 2)
     557            Traceback (most recent call last):
     558            ...
     559            ValueError: Kautz digraphs are defined for degree at least one.
     560
     561        An exception is raised when the diameter of the graph is less than one::
     562
     563            sage: G = digraphs.Kautz(2, 0)
     564            Traceback (most recent call last):
     565            ...
     566            ValueError: Kautz digraphs are defined for diameter at least one.
     567
     568
     569        REFERENCE:
     570
     571        .. [Kautz68] W. H. Kautz. Bounds on directed (d, k) graphs. Theory of
     572          cellular logic networks and machines, AFCRL-68-0668, SRI Project 7258,
     573          Final Rep., pp. 20-28, 1968.
     574        """
     575        if D < 1:
     576            raise ValueError("Kautz digraphs are defined for diameter at least one.")
     577
     578        from sage.combinat.words.words import Words
     579        from sage.rings.integer import Integer
     580
     581        my_alphabet = Words([str(i) for i in range(k+1)] if isinstance(k, Integer) else k, 1)
     582        if my_alphabet.size_of_alphabet() < 2:
     583            raise ValueError("Kautz digraphs are defined for degree at least one.")
     584
     585        if vertices == 'strings':
     586
     587            # We start building the set of vertices
     588            V = [i for i in my_alphabet]
     589            for i in range(D-1):
     590                VV = []
     591                for w in V:
     592                    VV += [w*a for a in my_alphabet if not w.has_suffix(a) ]
     593                V = VV
     594
     595            # We now build the set of arcs
     596            G = DiGraph()
     597            for u in V:
     598                for a in my_alphabet:
     599                    if not u.has_suffix(a):
     600                        G.add_edge(u.string_rep(), (u[1:]*a).string_rep(), a.string_rep())
     601
     602        else:
     603            d = my_alphabet.size_of_alphabet()-1
     604            G = digraphs.ImaseItoh( (d+1)*(d**(D-1)), d)
     605
     606        G.name( "Kautz digraph (k=%s, D=%s)"%(k,D) )
     607        return G
     608
    353609       
    354610    def RandomDirectedGN(self, n, kernel=lambda x:x, seed=None):
    355611        """