Path: blob/master/sage/combinat/enumeration_mod_permgroup.pyx
4068 views
r"""1Tools for enumeration modulo the action of a permutation group2"""3#*****************************************************************************4# Copyright (C) 2010-12 Nicolas Borie <nicolas.borie at math dot u-psud.fr>5#6# Distributed under the terms of the GNU General Public License (GPL)7#8# The full text of the GPL is available at:9# http://www.gnu.org/licenses/10#*****************************************************************************11from sage.structure.list_clone cimport ClonableIntArray12from sage.groups.perm_gps.permgroup_element cimport PermutationGroupElement13from cpython cimport bool1415cpdef list all_children(ClonableIntArray v, int max_part):16r"""17Returns all the children of an integer vector (:class:`~sage.structure.list_clone.ClonableIntArray`)18``v`` in the tree of enumeration by lexicographic order. The children of19an integer vector ``v`` whose entries have the sum `n` are all integer20vectors of sum `n+1` which follow ``v`` in the lexicographic order.2122That means this function adds `1` on the last non zero entries and the23following ones. For an integer vector `v` such that2425.. math::2627v = [ \dots, a , 0, 0 ] \text{ with } a \neq 0,2829then, the list of children is3031.. math::3233[ [ \dots, a+1 , 0, 0 ] , [ \dots, a , 1, 0 ], [ \dots, a , 0, 1 ] ].3435EXAMPLES::3637sage: from sage.combinat.enumeration_mod_permgroup import all_children38sage: from sage.structure.list_clone import IncreasingIntArrays39sage: v = IncreasingIntArrays()([1,2,3,4])40sage: all_children(v, -1)41[[1, 2, 3, 5]]42"""43cdef int l, j44cdef list all_children45cdef ClonableIntArray child46l = len(v)47all_children = []48j = l - 149while v._list[j] == 0 and j >= 1:50j = j - 151for i in range(j,l):52if (max_part < 0) or ((v[i]+1) <= max_part):53child = v.clone()54child._list[i] = v._list[i]+155child.set_immutable()56all_children.append(child)57return all_children5859cpdef int lex_cmp_partial(ClonableIntArray v1, ClonableIntArray v2, int step):60r"""61Partial comparison of the two lists according the lexicographic62order. It compares the ``step``-th first entries.6364EXAMPLES::6566sage: from sage.combinat.enumeration_mod_permgroup import lex_cmp_partial67sage: from sage.structure.list_clone import IncreasingIntArrays68sage: IA = IncreasingIntArrays()69sage: lex_cmp_partial(IA([0,1,2,3]),IA([0,1,2,4]),3)70071sage: lex_cmp_partial(IA([0,1,2,3]),IA([0,1,2,4]),4)72-173"""74cdef int i75if step < 0 or step > v1._len or step > v2._len:76raise IndexError, "list index out of range"7778for i in range(step):79if v1._list[i] != v2._list[i]:80break81if i<step:82if v1._list[i] > v2._list[i]:83return 184if v1._list[i] < v2._list[i]:85return -186return 08788cpdef int lex_cmp(ClonableIntArray v1, ClonableIntArray v2):89"""90Lexicographic comparison of :class:`~sage.structure.list_clone.ClonableIntArray`.9192INPUT:9394Two instances `v_1, v_2` of :class:`~sage.structure.list_clone.ClonableIntArray`9596OUPUT:9798``-1,0,1``, depending on whether `v_1` is lexicographically smaller, equal, or99greater than `v_2`.100101EXAMPLES::102103sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5),5)104sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5))105sage: J = IntegerVectorsModPermutationGroup(SymmetricGroup(6))106sage: v1 = I([2,3,1,2,3], check=False)107sage: v2 = I([2,3,2,3,2], check=False)108sage: v3 = J([2,3,1,2,3,1], check=False)109sage: from sage.combinat.enumeration_mod_permgroup import lex_cmp110sage: lex_cmp(v1, v1)1110112sage: lex_cmp(v1, v2)113-1114sage: lex_cmp(v2, v1)1151116sage: lex_cmp(v1, v3)117-1118sage: lex_cmp(v3, v1)1191120121"""122cdef int i123cdef int step = min(v1._len,v2._len)124for i in range(step):125if v1._list[i] != v2._list[i]:126break127if i<step:128if v1._list[i] > v2._list[i]:129return 1130if v1._list[i] < v2._list[i]:131return -1132if v1._len==v2._len:133return 0134if v1._len<v2._len:135return -1136return 1137138cpdef bool is_canonical(list sgs, ClonableIntArray v):139r"""140Returns ``True`` if the integer vector `v` is maximal with respect to141the lexicographic order in its orbit under the action of the142permutation group whose strong generating system is ``sgs``. Such143vectors are said to be canonical.144145Let `G` to be the permutation group which admit ``sgs`` as a strong146generating system. An integer vector `v` is said to be147canonical under the action of `G` if and only if:148149.. math::150151v = \max_{\text{lex order}} \{g \cdot v | g \in G \}152153EXAMPLES::154155sage: from sage.combinat.enumeration_mod_permgroup import is_canonical156sage: G = PermutationGroup([[(1,2,3,4)]])157sage: sgs = G.strong_generating_system()158sage: from sage.structure.list_clone import IncreasingIntArrays159sage: IA = IncreasingIntArrays()160sage: is_canonical(sgs, IA([1,2,3,6]))161False162"""163cdef int l, i, comp164cdef set to_analyse, new_to_analyse165cdef ClonableIntArray list_test, child166cdef PermutationGroupElement x167cdef list transversal168l = len(v)169to_analyse = set([v])170for i in range(l-1):171new_to_analyse = set([])172transversal = sgs[i]173for list_test in to_analyse:174for x in transversal:175child = x._act_on_array_on_position(list_test)176comp = lex_cmp_partial(v,child,i+1)177if comp == -1:178return False179if comp == 0:180new_to_analyse.add(child)181to_analyse = new_to_analyse182return True183184cpdef ClonableIntArray canonical_representative_of_orbit_of(list sgs, ClonableIntArray v):185r"""186Returns the maximal vector for the lexicographic order living in187the orbit of `v` under the action of the permutation group whose188strong generating system is ``sgs``. The maximal vector is also189called "canonical". Hence, this method returns the canonical190vector inside the orbit of `v`. If `v` is already canonical,191the method returns `v`.192193Let `G` to be the permutation group which admits ``sgs`` as a strong194generating system. An integer vector `v` is said to be195canonical under the action of `G` if and only if:196197.. math::198199v = \max_{\text{lex order}} \{g \cdot v | g \in G \}200201EXAMPLES::202203sage: from sage.combinat.enumeration_mod_permgroup import canonical_representative_of_orbit_of204sage: G = PermutationGroup([[(1,2,3,4)]])205sage: sgs = G.strong_generating_system()206sage: from sage.structure.list_clone import IncreasingIntArrays207sage: IA = IncreasingIntArrays()208sage: canonical_representative_of_orbit_of(sgs, IA([1,2,3,5]))209[5, 1, 2, 3]210"""211cdef int l,i,comp212cdef set to_analyse, new_to_analyse213cdef ClonableIntArray representative, list_test, child214cdef PermutationGroupElement x215representative = v216l = len(v)217to_analyse = set([v])218for i in range(l-1):219new_to_analyse = set([])220for list_test in to_analyse:221for x in sgs[i]:222child = x._act_on_array_on_position(list_test)223comp = lex_cmp_partial(representative,child,i+1)224if comp <= 0:225new_to_analyse.add(child)226to_analyse = new_to_analyse227representative = max(to_analyse)228return representative229230cpdef list canonical_children(list sgs, ClonableIntArray v, int max_part):231r"""232Returns the canonical children of the integer vector ``v``. This233function computes all children of the integer vector ``v`` via the234function :func:`all_children` and returns from this list only235these which are canonicals identified via the function236:func:`is_canonical`.237238EXAMPLES::239240sage: from sage.combinat.enumeration_mod_permgroup import canonical_children241sage: G = PermutationGroup([[(1,2,3,4)]])242sage: sgs = G.strong_generating_system()243sage: from sage.structure.list_clone import IncreasingIntArrays244sage: IA = IncreasingIntArrays()245sage: canonical_children(sgs, IA([1,2,3,5]), -1)246[]247"""248cdef ClonableIntArray child249return [child for child in all_children(v, max_part) if is_canonical(sgs, child)]250251cpdef set orbit(list sgs, ClonableIntArray v):252r"""253Returns the orbit of the integer vector ``v`` under the action of the254permutation group whose strong generating system is ``sgs``.255256NOTE:257258The returned orbit is a set. In the doctests, we convert it into a259sorted list.260261EXAMPLES::262263sage: from sage.combinat.enumeration_mod_permgroup import orbit, lex_cmp264sage: G = PermutationGroup([[(1,2,3,4)]])265sage: sgs = G.strong_generating_system()266sage: from sage.structure.list_clone import IncreasingIntArrays267sage: IA = IncreasingIntArrays()268sage: sorted(orbit(sgs, IA([1,2,3,4])), cmp=lex_cmp)269[[1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]270"""271cdef i,l272cdef set to_analyse, new_to_analyse273cdef ClonableIntArray list_test, child274cdef PermutationGroupElement x275cdef list out276l = len(v)277to_analyse = set([v])278for i in range(l-1):279new_to_analyse = set([])280for list_test in to_analyse:281for x in sgs[i]:282child = x._act_on_array_on_position(list_test)283new_to_analyse.add(child)284to_analyse = new_to_analyse285return to_analyse286287288