Ejemplo n.º 1
0
 def plot(self, **kwds):
     """
     EXAMPLES::
 
         sage: X = gauge_theories.threeSU(3)
         sage: print X.plot().description()
     """
     g = DiGraph(loops=True, sparse=True, multiedges=True)
     for G in self._gauge_groups:
         g.add_vertex(G)
     for field in self._fields:
         if isinstance(field, FieldBifundamental):
             g.add_edge(field.src, field.dst, field)
         if isinstance(field, FieldAdjoint):
             g.add_edge(field.node, field.node, field)
     return g.plot(vertex_labels=True, edge_labels=True, graph_border=True)
Ejemplo n.º 2
0
    def to_dag(self):
        """
        Returns a directed acyclic graph corresponding to the skew
        partition.

        EXAMPLES::

            sage: dag = SkewPartition([[3, 2, 1], [1, 1]]).to_dag()
            sage: dag.edges()
            [('0,1', '0,2', None), ('0,1', '1,1', None)]
            sage: dag.vertices()
            ['0,1', '0,2', '1,1', '2,0']
        """
        i = 0

        #Make the skew tableau from the shape
        skew = [[1]*row_length for row_length in self.outer()]
        inner = self.inner()
        for i in range(len(inner)):
            for j in range(inner[i]):
                skew[i][j] = None

        G = DiGraph()
        for row in range(len(skew)):
            for column in range(len(skew[row])):
                if skew[row][column] is not None:
                    string = "%d,%d" % (row, column)
                    G.add_vertex(string)
                    #Check to see if there is a node to the right
                    if column != len(skew[row]) - 1:
                        newstring = "%d,%d" % (row, column+1)
                        G.add_edge(string, newstring)

                    #Check to see if there is anything below
                    if row != len(skew) - 1:
                        if len(skew[row+1]) > column:
                            if skew[row+1][column] is not None:
                                newstring = "%d,%d" % (row+1, column)
                                G.add_edge(string, newstring)
        return G
Ejemplo n.º 3
0
    def to_dag(self):
        """
        Returns a directed acyclic graph corresponding to the skew
        partition.

        EXAMPLES::

            sage: dag = SkewPartition([[3, 2, 1], [1, 1]]).to_dag()
            sage: dag.edges()
            [('0,1', '0,2', None), ('0,1', '1,1', None)]
            sage: dag.vertices()
            ['0,1', '0,2', '1,1', '2,0']
        """
        i = 0

        #Make the skew tableau from the shape
        skew = [[1]*row_length for row_length in self.outer()]
        inner = self.inner()
        for i in range(len(inner)):
            for j in range(inner[i]):
                skew[i][j] = None

        G = DiGraph()
        for row in range(len(skew)):
            for column in range(len(skew[row])):
                if skew[row][column] is not None:
                    string = "%d,%d" % (row, column)
                    G.add_vertex(string)
                    #Check to see if there is a node to the right
                    if column != len(skew[row]) - 1:
                        newstring = "%d,%d" % (row, column+1)
                        G.add_edge(string, newstring)

                    #Check to see if there is anything below
                    if row != len(skew) - 1:
                        if len(skew[row+1]) > column:
                            if skew[row+1][column] is not None:
                                newstring = "%d,%d" % (row+1, column)
                                G.add_edge(string, newstring)
        return G
Ejemplo n.º 4
0
    def _digraph(self):
        r"""
        Constructs the underlying digraph and stores the result as an
        attribute.

        EXAMPLES::

            sage: from sage.combinat.yang_baxter_graph import SwapIncreasingOperator
            sage: ops = [SwapIncreasingOperator(i) for i in range(2)]
            sage: Y = YangBaxterGraph(root=(1,2,3), operators=ops)
            sage: Y._digraph
            Digraph on 6 vertices
        """
        digraph = DiGraph()
        digraph.add_vertex(self._root)
        queue = [self._root]
        while queue:
            u = queue.pop()
            for (v, l) in self._successors(u):
                if v not in digraph:
                    queue.append(v)
                digraph.add_edge(u, v, l)
        return digraph
Ejemplo n.º 5
0
    def _digraph(self):
        r"""
        Constructs the underlying digraph and stores the result as an
        attribute.

        EXAMPLES::
        
            sage: from sage.combinat.yang_baxter_graph import SwapIncreasingOperator
            sage: ops = [SwapIncreasingOperator(i) for i in range(2)]
            sage: Y = YangBaxterGraph(root=(1,2,3), operators=ops)
            sage: Y._digraph
            Digraph on 6 vertices
        """
        digraph = DiGraph()
        digraph.add_vertex(self._root)
        queue = [self._root]
        while queue:
            u = queue.pop()
            for (v, l) in self._succesors(u):
                if v not in digraph:
                    queue.append(v)
                digraph.add_edge(u, v, l)
        return digraph
Ejemplo n.º 6
0
class ParentBigOh(Parent,UniqueRepresentation):
    def __init__(self,ambiant):
        try:
            self._uniformizer = ambiant.uniformizer_name()
        except NotImplementedError:
            raise TypeError("Impossible to determine the name of the uniformizer")
        self._ambiant_space = ambiant
        self._models = DiGraph(loops=False)
        self._default_model = None
        Parent.__init__(self,ambiant.base_ring())
        if self.base_ring() is None:
            self._base_precision = None
        else:
            if self.base_ring() == ambiant:
                self._base_precision = self
            else:
                self._base_precision = ParentBigOh(self.base_ring())

    def __hash__(self):
        return id(self)

    def base_precision(self):
        return self._base_precision

    def precision(self):
        return self._precision

    def default_model(self):
        if self._default_mode is None:
            self.set_default_model()
        return self._default_model
    
    def set_default_model(self,model=None):
        if model is None:
            self._default_model = self._models.topological_sort()[-1]
        else:
            if self._models.has_vertex(model):
                self._default_model = model
            else:
                raise ValueError

    def add_model(self,model):
        from bigoh import BigOh
        if not isinstance(model,list):
            model = [model]
        for m in model:
            if not issubclass(m,BigOh):
                raise TypeError("A precision model must derive from BigOh but '%s' is not"%m)
            self._models.add_vertex(m)

    def delete_model(self,model):
        if isinstance(model,list):
            model = [model]
        for m in model:
            if self._models.has_vertex(m):
                self._models.delete_vertex(m)

    def update_model(self,old,new):
        from bigoh import BigOh
        if self._models.has_vertex(old):
            if not issubclass(new,BigOh):
                raise TypeError("A precision model must derive from BigOh but '%s' is not"%new)
            self._models.relabel({old:new})
        else:
            raise ValueError("Model '%m' does not exist"%old)

    def add_modelconversion(self,domain,codomain,constructor=None,safemode=False):
        if not self._models.has_vertex(domain):
            if safemode: return
            raise ValueError("Model '%s' does not exist"%domain)
        if not self._models.has_vertex(codomain):
            if safemode: return
            raise ValueError("Model '%s' does not exist"%codomain)
        path = self._models.shortest_path(codomain,domain)
        if len(path) > 0:
            raise ValueError("Adding this conversion creates a cycle")
        self._models.add_edge(domain,codomain,constructor)

    def delete_modelconversion(self,domain,codomain):
        if not self._models.has_vertex(domain):
            raise ValueError("Model '%s' does not exist"%domain)
        if not self._models.has_vertex(codomain):
            raise ValueError("Model '%s' does not exist"%codomain)
        if not self._models_has_edge(domain,codomain):
            raise ValueError("No conversion from %s to %s"%(domain,codomain))
        self._modelfs.delete_edge(domain,codomain)

    def uniformizer_name(self):
        return self._uniformizer

    def ambiant_space(self):
        return self._ambiant_space

    # ?!?
    def __call__(self,*args,**kwargs):
        return self._element_constructor_(*args,**kwargs)
    
    def _element_constructor_(self, *args, **kwargs):
        if kwargs.has_key('model'):
            del kwargs['model']
            return kwargs['model'](self, *args, **kwargs)
        if len(args) > 0:
            from precision.bigoh import BigOh, ExactBigOh
            arg = args[0]
            if isinstance(arg,BigOh) and arg.is_exact():
                return ExactBigOh(self)
            if self._models.has_vertex(arg.__class__) and arg.parent() is self:
                return arg
        if self._default_model is not None:
            try:
                return self._default_model(self,*args,**kwargs)
            except (AttributeError,ValueError,TypeError):
                pass
        models = self._models.topological_sort()
        models.reverse()
        for m in models:
            try:
                return m(self,*args,**kwargs)
            except (AttributeError,ValueError,TypeError,PrecisionError):
                pass
        raise PrecisionError("unable to create a BigOh object")

    def __repr__(self):
        return "Parent for BigOh in %s" % self._ambiant_space

    def models(self,graph=False):
        if graph:
            return self._models
        else:
            return self._models.vertices()

    def dimension(self):
        return self._ambiant_space.dimension()

    def indices_basis(self):
        return self._ambiant_space.indices_basis()
Ejemplo n.º 7
0
    def reduced_rauzy_graph(self, n):
        r"""
        Returns the reduced Rauzy graph of order `n` of self.

        INPUT:

        - ``n`` - non negative integer. Every vertex of a reduced
          Rauzy graph of order `n` is a factor of length `n` of self.

        OUTPUT:

        Looped multi-digraph

        DEFINITION:

        For infinite periodic words (resp. for finite words of type `u^i
        u[0:j]`), the reduced Rauzy graph of order `n` (resp. for `n`
        smaller or equal to `(i-1)|u|+j`) is the directed graph whose
        unique vertex is the prefix `p` of length `n` of self and which has
        an only edge which is a loop on `p` labelled by `w[n+1:|w|] p`
        where `w` is the unique return word to `p`.

        In other cases, it is the directed graph defined as followed.  Let
        `G_n` be the Rauzy graph of order `n` of self. The vertices are the
        vertices of `G_n` that are either special or not prolongable to the
        right or to the left. For each couple (`u`, `v`) of such vertices
        and each directed path in `G_n` from `u` to `v` that contains no
        other vertices that are special, there is an edge from `u` to `v`
        in the reduced Rauzy graph of order `n` whose label is the label of
        the path in `G_n`.
        
        .. NOTE::

            In the case of infinite recurrent non periodic words, this
            definition correspond to the following one that can be found in
            [1] and [2]  where a simple path is a path that begins with a
            special factor, ends with a special factor and contains no
            other vertices that are special:

            The reduced Rauzy graph of factors of length `n` is obtained
            from `G_n` by replacing each simple path `P=v_1 v_2 ...
            v_{\ell}` with an edge `v_1 v_{\ell}` whose label is the
            concatenation of the labels of the edges of `P`.

        EXAMPLES::

            sage: w = Word(range(10)); w
            word: 0123456789
            sage: g = w.reduced_rauzy_graph(3); g
            Looped multi-digraph on 2 vertices
            sage: g.vertices()
            [word: 012, word: 789]
            sage: g.edges()
            [(word: 012, word: 789, word: 3456789)]

        For the Fibonacci word::

            sage: f = words.FibonacciWord()[:100]
            sage: g = f.reduced_rauzy_graph(8);g
            Looped multi-digraph on 2 vertices
            sage: g.vertices()
            [word: 01001010, word: 01010010]
            sage: g.edges()
            [(word: 01001010, word: 01010010, word: 010), (word: 01010010, word: 01001010, word: 01010), (word: 01010010, word: 01001010, word: 10)]

        For periodic words::

            sage: from itertools import cycle
            sage: w = Word(cycle('abcd'))[:100]
            sage: g = w.reduced_rauzy_graph(3)
            sage: g.edges()
            [(word: abc, word: abc, word: dabc)]

        ::

            sage: w = Word('111')
            sage: for i in range(5) : w.reduced_rauzy_graph(i)
            Looped digraph on 1 vertex
            Looped digraph on 1 vertex
            Looped digraph on 1 vertex
            Looped multi-digraph on 1 vertex
            Looped multi-digraph on 0 vertices

        For ultimately periodic words::

            sage: sigma = WordMorphism('a->abcd,b->cd,c->cd,d->cd')
            sage: w = sigma.fixed_point('a')[:100]; w
            word: abcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd...
            sage: g = w.reduced_rauzy_graph(5)
            sage: g.vertices()
            [word: abcdc, word: cdcdc]
            sage: g.edges()
            [(word: abcdc, word: cdcdc, word: dc), (word: cdcdc, word: cdcdc, word: dc)]

        AUTHOR:

        Julien Leroy (March 2010): initial version

        REFERENCES:

        - [1] M. Bucci et al.  A. De Luca, A. Glen, L. Q. Zamboni, A
          connection between palindromic and factor complexity using
          return words," Advances in Applied Mathematics 42 (2009) 60-74.

        - [2] L'ubomira Balkova, Edita Pelantova, and Wolfgang Steiner.
          Sequences with constant number of return words. Monatsh. Math,
          155 (2008) 251-263.
        """
        from sage.graphs.all import DiGraph
        from copy import copy
        g = copy(self.rauzy_graph(n))      
        # Otherwise it changes the rauzy_graph function.
        l = [v for v in g if g.in_degree(v)==1 and g.out_degree(v)==1]
        if g.num_verts() !=0 and len(l)==g.num_verts():       
            # In this case, the Rauzy graph is simply a cycle.
            g = DiGraph()
            g.allow_loops(True)
            g.add_vertex(self[:n])
            g.add_edge(self[:n],self[:n],self[n:n+len(l)])
        else:
            g.allow_loops(True)
            g.allow_multiple_edges(True)
            for v in l:
                [i] = g.neighbors_in(v)
                [o] = g.neighbors_out(v)
                g.add_edge(i,o,g.edge_label(i,v)[0]*g.edge_label(v,o)[0])
                g.delete_vertex(v)
        return g
Ejemplo n.º 8
0
    def rauzy_graph(self, n):
        r"""
        Returns the Rauzy graph of the factors of length n of self.

        The vertices are the factors of length `n` and there is an edge from
        `u` to `v` if `ua = bv` is a factor of length `n+1` for some letters 
        `a` and `b`.  

        INPUT:

        - ``n`` - integer

        EXAMPLES::

            sage: w = Word(range(10)); w
            word: 0123456789
            sage: g = w.rauzy_graph(3); g
            Looped digraph on 8 vertices
            sage: WordOptions(identifier='')
            sage: g.vertices()
            [012, 123, 234, 345, 456, 567, 678, 789]
            sage: g.edges()
            [(012, 123, 3), 
             (123, 234, 4), 
             (234, 345, 5), 
             (345, 456, 6), 
             (456, 567, 7), 
             (567, 678, 8), 
             (678, 789, 9)]
            sage: WordOptions(identifier='word: ')

        ::

            sage: f = words.FibonacciWord()[:100]
            sage: f.rauzy_graph(8)
            Looped digraph on 9 vertices

        ::

            sage: w = Word('1111111')
            sage: g = w.rauzy_graph(3)
            sage: g.edges()
            [(word: 111, word: 111, word: 1)]

        ::

            sage: w = Word('111')
            sage: for i in range(5) : w.rauzy_graph(i)
            Looped multi-digraph on 1 vertex
            Looped digraph on 1 vertex
            Looped digraph on 1 vertex
            Looped digraph on 1 vertex
            Looped digraph on 0 vertices

        Multi-edges are allowed for the empty word::

            sage: W = Words('abcde')
            sage: w = W('abc')
            sage: w.rauzy_graph(0)
            Looped multi-digraph on 1 vertex
            sage: _.edges()
            [(word: , word: , word: a),
             (word: , word: , word: b),
             (word: , word: , word: c)]
        """
        from sage.graphs.digraph import DiGraph
        multiedges = True if n == 0 else False
        g = DiGraph(loops=True, multiedges=multiedges)
        if n == self.length():
            g.add_vertex(self)
        else:
            for w in self.factor_iterator(n+1):
                u = w[:-1]
                v = w[1:]
                a = w[-1:]
                g.add_edge(u,v,a)
        return g
Ejemplo n.º 9
0
    def forcing_oriented_graph(self):
        r"""
        Return the forcing oriented graph for a 3-dimensional vector
        configuration.

        This is the directed graph on shards. The hyperplane arrangement with
        base region corresponding to the acyclic vector configuration is
        congruence normal if and only if the directed graph on shards
        is acyclic.

        OUTPUT:

        An oriented graph

        EXAMPLES::

            sage: from cn_hyperarr.vector_classes import *
            sage: vc = VectorConfiguration([[1,0,0],[0,1,0],[0,0,1],[1,1,0],[0,1,1],[1,1,1]])
            sage: fog = vc.forcing_oriented_graph(); fog
            Digraph on 11 vertices
            sage: fog.num_edges()
            24
            sage: tau = AA((1+sqrt(5))/2)
            sage: ncn = [[2*tau+1,2*tau,tau],[2*tau+2,2*tau+1,tau+1],[1,1,1],[tau+1,tau+1,tau],[2*tau,2*tau,tau],[tau+1,tau+1,1],[1,1,0],[0,1,0],[1,0,0],[tau+1,tau,tau]]
            sage: ncn_conf = VectorConfiguration(ncn);
            sage: ncn_fog = ncn_conf.forcing_oriented_graph(); ncn_fog
            Digraph on 29 vertices
            sage: ncn_fog.num_edges()
            96
            sage: ncn_fog.is_directed_acyclic()
            False

        TESTS:

        The ambient dimension should be 3::

            sage: vc = VectorConfiguration([[1],[2],[3]])
            sage: vc.forcing_oriented_graph()
            Traceback (most recent call last):
            ...
            AssertionError: The ambient dimension is not 3
        """
        nb_pts = self.n_vectors()
        shard_covectors = self.shard_covectors()
        hic = self.line_covectors()

        G = DiGraph()
        for shard_cov in shard_covectors:
            G.add_vertex(shard_cov)
            shard_index = shard_cov.index(0)
            potential_shards = (v for v in G.vertices()
                                if v.index(0) != shard_index)
            for other_shard_cov in potential_shards:
                other_shard_index = other_shard_cov.index(0)
                # Get the potential ordering of forcing:
                forcing = True
                if other_shard_cov[shard_index] in [1, -1]:
                    # shard_cov -> other_shard_cov
                    first_cov, second_cov = shard_cov, other_shard_cov
                elif shard_cov[other_shard_index] in [1, -1]:
                    # other_shard_cov -> shard_cov
                    first_cov, second_cov = other_shard_cov, shard_cov
                else:
                    forcing = False
                if forcing:
                    # A forcing takes place
                    hic1, hic2 = hic[Set([shard_index, other_shard_index])]
                    sic1 = hic1 & shard_cov & other_shard_cov
                    sic2 = hic2 & shard_cov & other_shard_cov
                    if sic1 == hic1 or sic2 == hic2:
                        G.add_edge(first_cov, second_cov)
        return G.copy(immutable=True)