Ticket #14784: trac_14784-trees-to-posets-and-graphs-vp.patch

File trac_14784-trees-to-posets-and-graphs-vp.patch, 9.2 KB (added by VivianePons, 6 years ago)
  • sage/combinat/binary_tree.py

    # HG changeset patch
    # User Viviane Pons <vivianepons at gmail.com>
    # Date 1371804761 -7200
    # Node ID b47fd70ef197cb44dc83ea487b3ad3f19b4d6356
    # Parent  cab2d2f872f478b755675fa84705eaa5c64b3660
    #14784 Maps fros trees to graphs and posets
    Added maps from ordered trees and binary trees to undirected graphs and posets.
    
    diff --git a/sage/combinat/binary_tree.py b/sage/combinat/binary_tree.py
    a b class BinaryTree(AbstractClonableTree, C 
    595595        from sage.combinat.permutation import Permutation
    596596        return Permutation(self._postfix_word())
    597597
     598    @combinatorial_map(name="To complete tree")
     599    def as_ordered_tree(self,with_leaves=True):
     600        r"""
     601        Return the same tree seen as an ordered tree. By default, leaves
     602        are transformed into actual nodes.
     603
     604        EXAMPLES::
     605
     606            sage: bt = BinaryTree([]); bt
     607            [., .]
     608            sage: bt.as_ordered_tree()
     609            [[], []]
     610            sage: bt.as_ordered_tree(with_leaves = False)
     611            []
     612            sage: bt = bt.canonical_labelling(); bt
     613            1[., .]
     614            sage: bt.as_ordered_tree()
     615            1[None[], None[]]
     616            sage: bt.as_ordered_tree(with_leaves=False)
     617            1[]
     618        """
     619        if with_leaves:
     620            children = [child.as_ordered_tree(with_leaves) for child in self]
     621        else:
     622            children = [child.as_ordered_tree(with_leaves) for child in self if not child.is_empty()]
     623        if self in LabelledBinaryTrees():
     624            from sage.combinat.ordered_tree import LabelledOrderedTree
     625            return LabelledOrderedTree(children, label = self.label())
     626        else:
     627            from sage.combinat.ordered_tree import OrderedTree
     628            return OrderedTree(children)
     629
     630    @combinatorial_map(name="To graph")
     631    def to_undirected_graph(self, with_leaves = False):
     632        r"""
     633        Return the undirected graph obtained from the tree nodes and edges.
     634        Leafs are ignored by default but can set ``with_leaves`` to ``True``
     635        to obtain the graph of the complete tree.
     636
     637        EXAMPLES::
     638
     639            sage: bt = BinaryTree([])             
     640            sage: bt.to_undirected_graph()
     641            Graph on 1 vertex
     642            sage: bt.to_undirected_graph(with_leaves=True)
     643            Graph on 3 vertices
     644
     645        If the tree is labelled, we use its labelling to label the graph.
     646        Otherwise, we use the graph canonical labelling which means that
     647        two different trees can have the same graph.
     648
     649        EXAMPLES::
     650
     651            sage: bt = BinaryTree([[],[None,[]]])
     652            sage: bt.canonical_labelling()
     653            2[1[., .], 3[., 4[., .]]]
     654            sage: bt.canonical_labelling().to_undirected_graph().edges()
     655            [(1, 2, None), (2, 3, None), (3, 4, None)]
     656            sage: bt.to_undirected_graph().edges()
     657            [(0, 3, None), (1, 2, None), (2, 3, None)]
     658            sage: bt.canonical_labelling().to_undirected_graph() == bt.to_undirected_graph()
     659            False
     660            sage: BinaryTree([[],[]]).to_undirected_graph() == BinaryTree([[[],None],None]).to_undirected_graph()
     661            True
     662        """
     663        return self.as_ordered_tree(with_leaves).to_undirected_graph()
     664
     665    @combinatorial_map(name="To poset")
     666    def to_poset(self, with_leaves = False, root_to_leaf=False):
     667        r"""
     668        Return the poset obtained by interpreting the tree as a hasse
     669        diagram.
     670
     671        The default orientation is from leaves to root but you can
     672        pass ``root_to_leaf=True`` to obtain the inverse orientation.
     673
     674        Leafs are ignored by default but can set ``with_leaves`` to ``True``
     675        to obtain the poset of the complete tree.
     676
     677        INPUT:
     678
     679        - ``with_leaves`` -- boolean, true if leaves should be added to the poset
     680        - ``root_to_leaf`` -- boolean, true if the poset orientation should
     681          be from root to leaves. It is false by default.
     682
     683        EXAMPLES::
     684
     685            sage: bt = BinaryTree([])           
     686            sage: bt.to_poset()
     687            Finite poset containing 1 elements
     688            sage: bt.to_poset(with_leaves=True)
     689            Finite poset containing 3 elements
     690            sage: bt.to_poset(with_leaves=True).cover_relations()
     691            [[0, 2], [1, 2]]
     692            sage: bt = BinaryTree([])
     693            sage: bt.to_poset(with_leaves=True,root_to_leaf=True).cover_relations()
     694            [[0, 1], [0, 2]]
     695
     696        If the tree is labelled, we use its labelling to label the poset.
     697        Otherwise, we use the poset canonical labelling::
     698
     699            sage: bt = BinaryTree([[],[None,[]]]).canonical_labelling()
     700            sage: bt
     701            2[1[., .], 3[., 4[., .]]]
     702            sage: bt.to_poset().cover_relations()
     703            [[4, 3], [3, 2], [1, 2]]
     704        """
     705        return self.as_ordered_tree(with_leaves).to_poset(root_to_leaf)
    598706
    599707    @combinatorial_map(name="To 132 avoiding permutation")
    600708    def to_132_avoiding_permutation(self):
  • sage/combinat/ordered_tree.py

    diff --git a/sage/combinat/ordered_tree.py b/sage/combinat/ordered_tree.py
    a b class OrderedTree(AbstractClonableTree,  
    380380            word.append(0)
    381381        from sage.combinat.dyck_word import DyckWord
    382382        return DyckWord(word)
    383    
     383
     384    @combinatorial_map(name="To graph")
     385    def to_undirected_graph(self):
     386        r"""
     387        Return the undirected graph obtained from the tree nodes and edges.
     388
     389        EXAMPLES::
     390
     391            sage: t = OrderedTree([])         
     392            sage: t.to_undirected_graph()
     393            Graph on 1 vertex
     394            sage: t = OrderedTree([[[]],[],[]])
     395            sage: t.to_undirected_graph()
     396            Graph on 5 vertices
     397
     398        If the tree is labelled, we use its labelling to label the graph.
     399        Otherwise, we use the graph canonical labelling which means that
     400        two different trees can have the same graph.
     401
     402        EXAMPLES::
     403
     404            sage: t = OrderedTree([[[]],[],[]])     
     405            sage: t.canonical_labelling().to_undirected_graph()
     406            Graph on 5 vertices
     407            sage: t.canonical_labelling().to_undirected_graph() == t.to_undirected_graph()
     408            False
     409            sage: OrderedTree([[],[]]).to_undirected_graph() == OrderedTree([[[]]]).to_undirected_graph()
     410            True
     411            sage: OrderedTree([[],[],[]]).to_undirected_graph() == OrderedTree([[[[]]]]).to_undirected_graph()
     412            False
     413        """
     414        from sage.graphs.graph import Graph
     415        g = Graph()
     416        if self in LabelledOrderedTrees():
     417            relabel = False
     418        else:
     419            self = self.canonical_labelling()
     420            relabel = True
     421        roots = [self]
     422        g.add_vertex(name=self.label())
     423        while len(roots)!=0:
     424            node = roots.pop()
     425            for child in node:
     426                g.add_vertex(name=child.label())
     427                g.add_edge(child.label(), node.label())
     428                roots.append(child)
     429        if(relabel):
     430            g = g.canonical_label()
     431        return g
     432
     433    @combinatorial_map(name="To poset")
     434    def to_poset(self, root_to_leaf = False):
     435        r"""
     436        Return the poset obtained by interpreting the tree as a hasse
     437        diagram. The default orientation is from leaves to root but you can
     438        pass ``root_to_leaf=True`` to obtain the inverse orientation.
     439
     440        INPUT:
     441
     442        - ``root_to_leaf`` -- boolean, true if the poset orientation should
     443          be from root to leaves. It is false by default.
     444
     445        EXAMPLES::
     446
     447            sage: t = OrderedTree([])
     448            sage: t.to_poset()
     449            Finite poset containing 1 elements
     450            sage: p = OrderedTree([[[]],[],[]]).to_poset()
     451            sage: p.cover_relations()
     452            [[0, 4], [1, 4], [2, 3], [3, 4]]
     453            sage: p = OrderedTree([[[]],[],[]]).to_poset(root_to_leaf=True)
     454            sage: p.cover_relations()
     455            [[0, 2], [0, 3], [0, 4], [4, 1]]
     456
     457        If the tree is labelled, we use its labelling to label the poset.
     458        Otherwise, we use the poset canonical labelling::
     459
     460            sage: t = OrderedTree([[[]],[],[]]).canonical_labelling()
     461            sage: t                                       
     462            1[2[3[]], 4[], 5[]]
     463            sage: t.to_poset().cover_relations()
     464            [[5, 1], [4, 1], [3, 2], [2, 1]]
     465        """
     466        if self in LabelledOrderedTrees():
     467            relabel = False
     468        else:
     469            self = self.canonical_labelling()
     470            relabel = True
     471        relations = []
     472        elements = [self.label()]
     473        roots = [self]
     474        while len(roots)!=0:
     475            node = roots.pop()
     476            for child in node:
     477                elements.append(child.label())
     478                relations.append((node.label(),child.label()) if root_to_leaf else (child.label(),node.label()))
     479                roots.append(child)
     480        from sage.combinat.posets.posets import Poset
     481        p = Poset([elements, relations])
     482        if relabel:
     483            p = p.canonical_label()
     484        return p
     485
    384486    @combinatorial_map(order=2,name="Left-right symmetry")
    385487    def left_right_symmetry(self):
    386488        r"""