Ticket #14412: trac_14412.patch

File trac_14412.patch, 10.5 KB (added by ncohen, 8 years ago)
  • sage/combinat/root_system/root_lattice_realizations.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1365096692 -7200
    # Node ID 75923589c5e2b47b2265c989a2f6ae5d4421ee24
    # Parent  b2eea661627f6318598b4c6b92f3f2618aa17f60
    Bug in GenericGraph.longest_path because of a bug in DiGraph.(incoming/outgoing)_edge*
    
    diff --git a/sage/combinat/root_system/root_lattice_realizations.py b/sage/combinat/root_system/root_lattice_realizations.py
    a b  
    392392            """
    393393            if self.dynkin_diagram().rank() == 1:
    394394                return self.simple_roots()[self.index_set()[0]]
    395             longest=self.dynkin_diagram().outgoing_edges()[0]
    396             for j in self.dynkin_diagram().outgoing_edges():
     395            longest=self.dynkin_diagram().edge_iterator().next()
     396            for j in self.dynkin_diagram().edge_iterator():
    397397                if j[2]>longest[2]:
    398398                    longest=j
    399399            return self.simple_roots()[longest[0]]
  • sage/graphs/digraph.py

    diff --git a/sage/graphs/digraph.py b/sage/graphs/digraph.py
    a b  
    10351035
    10361036    ### Edge Handlers
    10371037
    1038     def incoming_edge_iterator(self, vertices=None, labels=True):
     1038    def incoming_edge_iterator(self, vertices, labels=True):
    10391039        """
    1040         Return an iterator over all arriving edges from vertices, or over
    1041         all edges if vertices is None.
    1042        
     1040        Return an iterator over all arriving edges from vertices.
     1041
     1042        INPUT:
     1043
     1044        - ``vertices`` -- a vertex or a list of vertices
     1045
     1046        - ``labels`` (boolean) -- whether to return edges as pairs of vertices,
     1047          or as triples containing the labels.
     1048
    10431049        EXAMPLES::
    1044        
     1050
    10451051            sage: D = DiGraph( { 0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1] } )
    10461052            sage: for a in D.incoming_edge_iterator([0]):
    10471053            ...    print a
     
    10561062            vertices = [v for v in vertices if v in self]
    10571063        return self._backend.iterator_in_edges(vertices, labels)
    10581064
    1059     def incoming_edges(self, vertices=None, labels=True):
     1065    def incoming_edges(self, vertices, labels=True):
    10601066        """
    10611067        Returns a list of edges arriving at vertices.
    1062        
     1068
    10631069        INPUT:
    1064        
    1065        
    1066         -  ``labels`` - if False, each edge is a tuple (u,v) of
    1067            vertices.
    1068        
    1069        
     1070
     1071        - ``vertices`` -- a vertex or a list of vertices
     1072
     1073        - ``labels`` (boolean) -- whether to return edges as pairs of vertices,
     1074          or as triples containing the labels.
     1075
    10701076        EXAMPLES::
    1071        
     1077
    10721078            sage: D = DiGraph( { 0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1] } )
    10731079            sage: D.incoming_edges([0])
    10741080            [(1, 0, None), (4, 0, None)]
    10751081        """
    10761082        return list(self.incoming_edge_iterator(vertices, labels=labels))
    10771083
    1078     def outgoing_edge_iterator(self, vertices=None, labels=True):
     1084    def outgoing_edge_iterator(self, vertices, labels=True):
    10791085        """
    1080         Return an iterator over all departing edges from vertices, or over
    1081         all edges if vertices is None.
    1082        
     1086        Return an iterator over all departing edges from vertices.
     1087
     1088        INPUT:
     1089
     1090        - ``vertices`` -- a vertex or a list of vertices
     1091
     1092        - ``labels`` (boolean) -- whether to return edges as pairs of vertices,
     1093          or as triples containing the labels.
     1094
    10831095        EXAMPLES::
    1084        
     1096
    10851097            sage: D = DiGraph( { 0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1] } )
    10861098            sage: for a in D.outgoing_edge_iterator([0]):
    10871099            ...    print a
     
    10971109            vertices = [v for v in vertices if v in self]
    10981110        return self._backend.iterator_out_edges(vertices, labels)
    10991111
    1100     def outgoing_edges(self, vertices=None, labels=True):
     1112    def outgoing_edges(self, vertices, labels=True):
    11011113        """
    11021114        Returns a list of edges departing from vertices.
    1103        
     1115
    11041116        INPUT:
    1105        
    1106        
    1107         -  ``labels`` - if False, each edge is a tuple (u,v) of
    1108            vertices.
    1109        
    1110        
     1117
     1118        - ``vertices`` -- a vertex or a list of vertices
     1119
     1120        - ``labels`` (boolean) -- whether to return edges as pairs of vertices,
     1121          or as triples containing the labels.
     1122
    11111123        EXAMPLES::
    1112        
     1124
    11131125            sage: D = DiGraph( { 0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1] } )
    11141126            sage: D.outgoing_edges([0])
    11151127            [(0, 1, None), (0, 2, None), (0, 3, None)]
  • sage/graphs/generic_graph.py

    diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py
    a b  
    53635363            ValueError: algorithm must be either 'backtrack' or 'MILP'
    53645364
    53655365        Disconnected graphs not weighted::
    5366        
     5366
    53675367            sage: g1 = graphs.PetersenGraph()
    53685368            sage: g2 = 2 * g1
    53695369            sage: lp1 = g1.longest_path()
     
    54185418            ...           not max(lp.in_degree()) <= 1 or
    54195419            ...           not lp.is_connected()):
    54205420            ...           print("Error!")
     5421            ...           print g.edges()
    54215422            ...           break
    54225423
    54235424        :trac:`13019`::
     
    54255426            sage: g = graphs.CompleteGraph(5).to_directed()
    54265427            sage: g.longest_path(s=1,t=2)
    54275428            Subgraph of (Complete graph): Digraph on 5 vertices
     5429
     5430        :trac:`14412`::
     5431
     5432            sage: l = [(0, 1), (0, 3), (2, 0)]
     5433            sage: G = DiGraph(l)
     5434            sage: G.longest_path().edges()
     5435            [(0, 1, None), (2, 0, None)]
    54285436        """
    54295437        if use_edge_labels:
    54305438            algorithm = "MILP"
     
    54485456        # Stupid cases
    54495457        # - Graph having <= 1 vertex.
    54505458        #
    5451         # - The source has outdegree 0 in a directed graph, or 
     5459        # - The source has outdegree 0 in a directed graph, or
    54525460        #   degree 0, or is not a vertex of the graph.
    54535461        #
    54545462        # - The destination has indegree 0 in a directed graph, or
     
    54855493
    54865494        # Epsilon... Must be less than 1/(n+1), but we want to avoid
    54875495        # numerical problems...
    5488         epsilon = 1/(6*float(self.order()))
     5496        epsilon = 1/(2*float(self.order()))
    54895497
    54905498        # Associating a weight to a label
    54915499        if use_edge_labels:
     
    54945502            weight = lambda x: 1
    54955503
    54965504        from sage.numerical.mip import MixedIntegerLinearProgram
    5497         p = MixedIntegerLinearProgram()
    5498        
     5505        p = MixedIntegerLinearProgram(solver=solver)
     5506
    54995507        # edge_used[(u,v)] == 1 if (u,v) is used
    55005508        edge_used = p.new_variable(binary=True)
    55015509
     
    55075515        vertex_used = p.new_variable(binary=True)
    55085516
    55095517        if self._directed:
     5518
    55105519            # if edge uv is used, vu can not be
    55115520            for u, v in self.edges(labels=False):
    55125521                if self.has_edge(v, u):
    5513                     p.add_constraint(edge_used[(u,v)] + edge_used[(v,u)], max=1)
     5522                    p.add_constraint(edge_used[(u,v)] + edge_used[(v,u)] <= 1)
     5523
    55145524            # A vertex is used if one of its incident edges is
    5515             for v in self:
    5516                 for e in self.incoming_edges(labels=False):
    5517                     p.add_constraint(vertex_used[v] - edge_used[e], min=0)
    5518                 for e in self.outgoing_edges(labels=False):
    5519                     p.add_constraint(vertex_used[v] - edge_used[e], min=0)
     5525            for u,v in self.edges(labels = False):
     5526                p.add_constraint(vertex_used[v] >= edge_used[(u,v)])
     5527                p.add_constraint(vertex_used[u] >= edge_used[(u,v)])
     5528
    55205529            # A path is a tree. If n vertices are used, at most n-1 edges are
    55215530            p.add_constraint(
    5522                 p.sum(vertex_used[v] for v in self)
    5523                 - p.sum(edge_used[e] for e in self.edges(labels=False)),
    5524                 min=1, max=1)
     5531                  p.sum(vertex_used[v] for v in self)
     5532                - p.sum(edge_used[e] for e in self.edges(labels=False))
     5533                  == 1)
     5534
    55255535            # A vertex has at most one incoming used edge and at most
    55265536            # one outgoing used edge
    55275537            for v in self:
    55285538                p.add_constraint(
    5529                     p.sum(edge_used[(u,v)] for u in self.neighbors_in(v)),
    5530                     max=1)
     5539                    p.sum(edge_used[(u,v)] for u in self.neighbors_in(v)) <= 1)
    55315540                p.add_constraint(
    5532                     p.sum(edge_used[(v,u)] for u in self.neighbors_out(v)),
    5533                     max=1)
     5541                    p.sum(edge_used[(v,u)] for u in self.neighbors_out(v)) <= 1)
     5542
    55345543            # r_edge_used is "more" than edge_used, though it ignores
    55355544            # the direction
    55365545            for u, v in self.edges(labels=False):
    5537                 p.add_constraint(r_edge_used[(u,v)]
    5538                                  + r_edge_used[(v,u)]
    5539                                  - edge_used[(u,v)],
    5540                                  min=0)
     5546                p.add_constraint(r_edge_used[(u,v)] + r_edge_used[(v,u)]
     5547                                 >= edge_used[(u,v)])
     5548
    55415549            # No cycles
    55425550            for v in self:
    55435551                p.add_constraint(
    5544                     p.sum(r_edge_used[(u,v)] for u in self.neighbors(v)),
    5545                     max=1-epsilon)
     5552                    p.sum(r_edge_used[(u,v)] for u in self.neighbors(v))
     5553                    <= 1-epsilon)
     5554
    55465555            # Enforcing the source if asked.. If s is set, it has no
    55475556            # incoming edge and exactly one son
    55485557            if s is not None:
     
    55525561                p.add_constraint(
    55535562                    p.sum(edge_used[(s,u)] for u in self.neighbors_out(s)),
    55545563                    min=1, max=1)
     5564
    55555565            # Enforcing the destination if asked.. If t is set, it has
    55565566            # no outgoing edge and exactly one parent
    55575567            if t is not None:
     
    55615571                p.add_constraint(
    55625572                    p.sum(edge_used[(t,u)] for u in self.neighbors_out(t)),
    55635573                    max=0, min=0)
     5574
    55645575            # Defining the objective
    55655576            p.set_objective(
    55665577                p.sum(weight(l) * edge_used[(u,v)] for u, v, l in self.edges()))
     
    56095620        # Computing the result. No exception has to be raised, as this
    56105621        # problem always has a solution (there is at least one edge,
    56115622        # and a path from s to t if they are specified).
    5612         p.solve(solver=solver, log=verbose)
     5623        p.solve(log=verbose)
    56135624        edge_used = p.get_values(edge_used)
    56145625        vertex_used = p.get_values(vertex_used)
    56155626        if self._directed: