Ticket #13691: trac_13691.patch

File trac_13691.patch, 5.9 KB (added by ncohen, 8 years ago)
  • sage/graphs/graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1352371472 -3600
    # Node ID 20b18dfdeefa233d99d977f3c4459484450235df
    # Parent  b52d6a436c3291c6f37899a1aca344bfaddaf3e3
    Implements Graph.has_homomorphism_to
    
    diff --git a/sage/graphs/graph.py b/sage/graphs/graph.py
    a b  
    102102    :meth:`~Graph.minor` | Returns the vertices of a minor isomorphic to `H` in the current graph.
    103103    :meth:`~Graph.independent_set_of_representatives` | Returns an independent set of representatives.
    104104    :meth:`~Graph.coloring` | Returns the first (optimal) proper vertex-coloring found.
     105    :meth:`~Graph.has_homomorphism_to` | Checks whether there is a morphism between two graphs.
    105106    :meth:`~Graph.chromatic_number` | Returns the minimal number of colors needed to color the vertices of the graph.
    106107    :meth:`~Graph.chromatic_polynomial` | Returns the chromatic polynomial of the graph.
    107108    :meth:`~Graph.is_perfect` | Tests whether the graph is perfect.
     
    30383039        else:
    30393040            raise ValueError('algorithm must be set to either "Edmonds" or "LP"')
    30403041
     3042    def has_homomorphism_to(self, H, core = False, solver = None, verbose = 0):
     3043        r"""
     3044        Checks whether there is a homomorphism between two graphs.
     3045
     3046        A homomorphism from a graph `G` to a graph `H` is a function
     3047        `\phi:V(G)\mapsto V(H)` such that for any edge `uv \in E(G)` the pair
     3048        `\phi(u)\phi(v)` is an edge of `H`.
     3049
     3050        Saying that a graph can be `k`-colored is equivalent to saying that it
     3051        has a homomorphism to `K_k`, the complete graph on `k` elements.
     3052
     3053        For more information, see the `Wikipedia article on graph homomorphisms
     3054        <Graph_homomorphism>`_.
     3055
     3056        INPUT:
     3057
     3058        - ``H`` -- the graph to which ``self`` should be sent.
     3059
     3060        - ``core`` (boolean) -- whether to minimize the size of the mapping's
     3061          image (see note below). This is set to ``False`` by default.
     3062
     3063        - ``solver`` -- (default: ``None``) Specify a Linear Program (LP)
     3064          solver to be used. If set to ``None``, the default one is used. For
     3065          more information on LP solvers and which default solver is used, see
     3066          the method
     3067          :meth:`solve <sage.numerical.mip.MixedIntegerLinearProgram.solve>`
     3068          of the class
     3069          :class:`MixedIntegerLinearProgram <sage.numerical.mip.MixedIntegerLinearProgram>`.
     3070
     3071        - ``verbose`` -- integer (default: ``0``). Sets the level of
     3072          verbosity. Set to 0 by default, which means quiet.
     3073
     3074        .. NOTE::
     3075
     3076           One can compute the core of a graph (with respect to homomorphism)
     3077           with this method ::
     3078
     3079               sage: g = graphs.CycleGraph(10)
     3080               sage: mapping = g.has_homomorphism_to(g, core = True)
     3081               sage: print "The size of the core is",len(set(mapping.values()))
     3082               The size of the core is 2
     3083
     3084        OUTPUT:
     3085
     3086        This method returns ``False`` when the homomorphism does not exist, and
     3087        returns the homomorphism otherwise as a dictionnary associating a vertex
     3088        of `H` to a vertex of `G`.
     3089
     3090        EXAMPLE:
     3091
     3092        Is Petersen's graph 3-colorable::
     3093
     3094            sage: P = graphs.PetersenGraph()
     3095            sage: P.has_homomorphism_to(graphs.CompleteGraph(3)) is not False
     3096            True
     3097
     3098        An odd cycle admits a homomorphism to a smaller odd cycle, but not to an
     3099        even cycle::
     3100
     3101            sage: g = graphs.CycleGraph(9)
     3102            sage: g.has_homomorphism_to(graphs.CycleGraph(5)) is not False
     3103            True
     3104            sage: g.has_homomorphism_to(graphs.CycleGraph(7)) is not False
     3105            True
     3106            sage: g.has_homomorphism_to(graphs.CycleGraph(4)) is not False
     3107            False
     3108        """
     3109
     3110        from sage.numerical.mip import MixedIntegerLinearProgram, MIPSolverException
     3111        p = MixedIntegerLinearProgram(solver=solver, maximization = False)
     3112        b = p.new_variable(binary = True)
     3113
     3114        # Each vertex has an image
     3115        for ug in self:
     3116            p.add_constraint(p.sum([b[ug,uh] for uh in H]) == 1)
     3117
     3118        nonedges = H.complement().edges(labels = False)
     3119        for ug,vg in self.edges(labels = False):
     3120            # Two adjacent vertices cannot be mapped to the same element
     3121            for uh in H:
     3122                p.add_constraint(b[ug,uh] + b[vg,uh] <= 1)
     3123
     3124            # Two adjacent vertices cannot be mapped to no adjacent vertices
     3125            for uh,vh in nonedges:
     3126                p.add_constraint(b[ug,uh] + b[vg,vh] <= 1)
     3127                p.add_constraint(b[ug,vh] + b[vg,uh] <= 1)
     3128
     3129        # Minimize the mapping's size
     3130        if core:
     3131
     3132            # the value of m is one if the corresponding vertex of h is used.
     3133            m = p.new_variable()
     3134            for uh in H:
     3135                for ug in self:
     3136                    p.add_constraint(b[ug,uh] <= m[uh])
     3137
     3138            p.set_objective(p.sum([m[vh] for vh in H]))
     3139
     3140        try:
     3141            p.solve(log = verbose)
     3142            b = p.get_values(b)
     3143            mapping = dict(map(lambda y:y[0],filter(lambda x:x[1], b.items())))
     3144            return mapping
     3145
     3146        except MIPSolverException:
     3147            return False
     3148
    30413149    def fractional_chromatic_index(self, verbose_constraints = 0, verbose = 0):
    30423150        r"""
    30433151        Computes the fractional chromatic index of ``self``
     
    48174925        """
    48184926        Returns the core number for each vertex in an ordered list.
    48194927
     4928        (for homomorphisms cores, see the :meth:`Graph.has_homomorphism_to`
     4929        method)
    48204930
    48214931        **DEFINITIONS**
    48224932
     
    48764986
    48774987             By default, ``with_labels = False``.
    48784988
     4989        .. SEEALSO::
     4990
     4991           * Graph cores is also a notion related to graph homomorphisms. For
     4992             this second meaning, see :meth:`Graph.has_homomorphism_to`.
     4993
    48794994        REFERENCE:
    48804995
    48814996        .. [WPkcore] K-core. Wikipedia. (2007). [Online] Available: